当你编写程序时,编译器会检查以确保你遵循了C++语言的规则(假设你已根据课程0.10 -- 配置你的编译器:编译器扩展关闭了编译器扩展)。如果你所做的操作明确违反了语言规则,那么你的程序就是格式不正确的。
在大多数情况下,当编译器遇到某种问题时,它会发出诊断消息(通常简称为诊断)。C++标准没有定义诊断消息应如何分类、措辞,以及这些问题应如何影响程序的编译。然而,现代编译器通常已采用以下约定:
- 诊断错误(简称错误)意味着编译器已决定停止编译,因为它无法继续,或者认为错误严重到必须停止。由编译器生成的诊断错误通常称为编译错误、编译器错误或编译时错误。
- 诊断警告(简称警告)意味着编译器已决定不停止编译。在这种情况下,问题会被简单地忽略,编译会继续进行。
关键见解
编译器决定一个非阻塞性问题是警告还是错误。虽然它们通常在分类上保持一致,但在某些情况下,编译器可能不一致——同一个问题,一个编译器可能发出错误,而另一个编译器可能发出警告。
为了帮助你确定问题所在,诊断消息通常包含编译器发现问题的文件名和行号,以及关于预期与实际发现内容的文本。实际问题可能在该行,也可能在前面一行。一旦你解决了导致诊断的问题,你可以尝试再次编译,看看是否不再生成相关的诊断消息。
在某些情况下,编译器可能会识别出不违反语言规则,但它认为可能不正确的代码。在这种情况下,编译器可能会决定发出警告,以提醒程序员某些地方似乎出了问题。这些问题可以通过修复警告指出的问题来解决,或者通过重写问题代码行,使其不再生成警告。
致进阶读者
我们在课程7.7 -- 外部链接和变量前向声明中展示了一个技术上合法但现代编译器认为可疑的语句示例。
在极少数情况下,可能需要明确告诉编译器不要为特定代码行生成特定警告。C++ 不支持官方的方法来实现这一点,但许多独立的编译器(包括 Visual Studio 和 GCC)提供了解决方案(通过非可移植的 #pragma 指令)来暂时禁用警告。
最佳实践
不要让警告堆积如山。遇到警告时就解决它们(就像解决错误一样)。否则,关于严重问题的警告可能会淹没在关于非严重问题的警告中。
如果链接时发生无法解决的问题,链接器也可能生成诊断错误。
提高你的警告级别
默认情况下,大多数编译器只会针对最明显的问题生成警告。然而,你可以要求编译器在提供警告方面更加积极,这样做通常是个好主意。
最佳实践
提高你的警告级别,尤其是在学习过程中。额外的诊断信息可能有助于识别可能导致程序故障的编程错误。
对于 Visual Studio 用户
要提高警告级别,请在“解决方案资源管理器”窗口中右键单击你的项目名称,然后选择“属性”。

在“项目”对话框中,首先确保“配置”字段设置为“所有配置”。
然后选择 C/C++ > 属性页 > 常规,并将“警告级别”设置为“级别4 (/W4)”。

注意:不要选择 启用所有警告 (/Wall),否则你将淹没在 C++ 标准库生成的警告中。
Visual Studio 默认禁用有符号/无符号转换警告,但这些警告很有用,因此如果你使用 Visual Studio 2019 或更高版本,让我们启用它们。
- 在 C/C++ > 命令行 选项卡下,在 附加选项 中添加
/w44365
。这会告诉编译器在警告级别 4(你已在上面启用)启用有符号/无符号转换警告。 - 从 C/C++ > 外部包含 选项卡,设置 外部头文件警告级别 为 级别3 (/external:W3)。这会告诉编译器以警告级别 3(而不是 4)编译标准库头文件,这样编译这些头文件就不会触发此警告。
“外部包含”选项卡未显示在上面的图中,但它出现在 VS Community 2019 或更高版本中,“浏览信息”和“高级”选项卡之间。请参阅此链接,其中包含包含“外部包含”选项卡的对话框的最新照片。
如果以上设置正确,编译以下程序应该会生成警告 C4365
void foo(int)
{
}
int main()
{
unsigned int x { 5 };
foo(x);
return 0;
}
如果未看到警告,请检查“输出”和“错误列表”选项卡(如果存在)。
对于 Code::Blocks 用户
从“设置”菜单 > “编译器” > “编译器设置”选项卡,找到并勾选与 -Wall、-Weffc++ 和 -Wextra 相关的选项。

然后转到“其他编译器选项”选项卡,并在以下文本编辑区域添加 -Wconversion -Wsign-conversion

注意: -Werror 参数将在下面解释。
对于 gcc 用户
在命令行中添加以下标志: -Wall -Weffc++ -Wextra -Wconversion -Wsign-conversion
对于 VS Code 用户
打开 tasks.json 文件,找到“args”,然后在该部分内找到行 “${file}”。
在 “${file}” 行上方,添加新行,每行包含以下命令:
"-Wall", "-Weffc++", "-Wextra", "-Wconversion", "-Wsign-conversion",
将警告视为错误
还可以告诉编译器将所有警告视为错误(在这种情况下,如果编译器发现任何警告,它将停止编译)。这是一个强制执行“应该修复所有警告”建议的好方法(如果你缺乏自律,我们大多数人都缺乏)。
最佳实践
启用“将警告视为错误”。这将强制你解决所有导致警告的问题。
对于 Visual Studio 用户
要将警告视为错误,请在“解决方案资源管理器”窗口中右键单击你的项目名称,然后选择“属性”。

在“项目”对话框中,首先确保“配置”字段设置为“所有配置”。
然后选择 C/C++ > 常规 选项卡,并将 将警告视为错误 设置为 是 (/WX)。

对于 Code::Blocks 用户
从 设置菜单 > 编译器 > 其他编译器选项 选项卡,在文本编辑区域添加 -Werror

对于 gcc 用户
在命令行中添加以下标志: -Werror
对于 VS Code 用户
在 tasks.json
文件中,在“${file}”之前添加以下标志,每行一个:
"-Werror",