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