头文件包含路径为何导致g++编译出现不同行为与警告?
问题
使用命令g++ -Wall -Wextra -std=c++2a -c /root/exodus/test/src/test_MB.cpp -H -Itemp编译时会出现警告,但使用g++ -Wall -Wextra -std=c++2a -c /root/exodus/test/src/test_MB.cpp -H编译时无警告。已确认/temp/exodus下的三个头文件与/usr/local/include/exodus中的完全一致。
以下是编译输出的diff结果(-H参数用于验证头文件包含位置):
07:20:08 root@de1:~/exodus/test/src# diff temp_warning usr_local_include --color=always 13,14c13,14 < . temp/exodus/program.h < .. temp/exodus/exodus.h --- > . /usr/local/include/exodus/program.h > .. /usr/local/include/exodus/exodus.h 244c244 < ... temp/exodus/exomacros.h --- > ... /usr/local/include/exodus/exomacros.h 248,261d247 < In file included from temp/exodus/exodus.h:39, < from temp/exodus/program.h:3, < from /root/exodus/test/src/test_MB.cpp:4: < /root/exodus/test/src/test_MB.cpp: In member function ‘exodus::var ExodusProgram::test_ioconv(exodus::ExodusProgramBase::in, exodus::ExodusProgramBase::in)’: < temp/exodus/exomacros.h:124:12: warning: logical not is only applied to the left hand side of comparison [-Wlogical-not-parentheses] < 124 | #define eq == < | ^~ < /root/exodus/test/src/test_MB.cpp:14:27: note: in expansion of macro ‘eq’ < 14 | if (not ovar.iconv("MB") eq ivar) < | ^~ < /root/exodus/test/src/test_MB.cpp:14:6: note: add parentheses around left hand side expression to silence this warning < 14 | if (not ovar.iconv("MB") eq ivar) < | ^~~~~~~~~~~~~~~~~~~~ < | ( )
疑问:为何仅因头文件包含路径不同,g++就产生不同的编译警告?
分析与解答
这是GCC针对不同目录的警告策略差异导致的:
/usr/local/include是GCC默认识别的系统头文件目录,对于这类目录下的头文件,GCC会自动抑制部分警告(比如-Wlogical-not-parentheses这类针对宏定义的警告),避免系统或第三方库代码产生大量无关告警。- 通过
-Itemp指定的temp属于自定义头文件目录,GCC不会对该目录下的头文件启用警告抑制,因此宏展开时会触发逻辑括号相关警告。
哪怕两个目录下的头文件内容完全一致,GCC也会根据头文件所在的目录类型决定是否启用特定警告。要统一警告行为,可选择以下方案:
- 用
-isystem temp替代-Itemp,将temp标记为系统头文件目录,让GCC自动抑制相关警告; - 显式添加
-Wno-logical-not-parentheses参数关闭该警告; - 修改代码,在
not表达式外添加括号:if ((not ovar.iconv("MB")) eq ivar),从根源消除警告触发条件。
内容的提问来源于stack exchange,提问作者Abazoo
相关产品推荐
相关产品推荐

