g++
运行是安全的,这与您的操作系统和环境变量设置有关。g++ -std=c++98 -std=c++11 ...
使用C++11编译会有影响吗?我在文档中没有找到明确的确认,但是我看到
-O
标志表现出这种方式。g++
运行是安全的,这与您的操作系统和环境变量设置有关。g++ -std=c++98 -std=c++11 ...
-O
标志表现出这种方式。GCC手册没有说明任何互斥的-std=...
选项中最后一个会生效。第一次出现或最后一次出现是唯一的选择。有许多GCC标志需要从有限集合中采取互斥的替代值,至少在翻译单元的语言模块方面是互斥的。简称为mutex选项。似乎很少有文档记录最后一个设置会生效。你已经注意到了,对于-O
选项进行了记录,并且通常以一般术语记录互斥警告选项,也许还有其他选项。从未记录多个设置的第一次会生效,因为这是不正确的。
文档倾向于使用unix-likes OSes命令用法的历史惯例,但不完全一致。如果一个命令接受mutex选项,则该选项的最后一次出现生效。如果该命令非常不寻常地仅作用于选项的第一次出现,则该命令接受后续出现实际上会是错误的:它应该给出使用错误。
这是一种惯例。该惯例有助于使用尊重它的工具进行脚本编写,例如,脚本可以调用一个工具并传递某个互斥选项的默认设置,但允许用户通过脚本参数覆盖该设置,其值可以简单地附加到默认调用中。main.cpp
#include <cstdio>
#if __cplusplus >= 201103L
static const char * str = "C++11";
#else
static const char * str = "Not C++11";
#endif
int main()
{
printf("%s\n%d\n",str,str); // Format `%d` for `str` mismatch
return 0;
}
使用命令行:
g++ -std=c++98 -std=c++11 -m32 -m64 -O0 -O1 -g3 -g0 \
-Wformat -Wno-format -o wrong -o right main.cpp
请求矛盾的选项对:
-std=c++98 -std=c++11
:符合C++98。符合C++11。-m32 -m64
:生成32位代码。生成64位代码。-O0 -O1
:不进行任何优化。优化到1级。-g3 -g0
:发出最大的调试信息。不发出调试信息。-Wformat -Wno-format
。检查printf
参数是否正确。不检查它们。-o wrong -o right
。输出程序wrong
。输出程序right
它成功构建,没有诊断:
$ echo "[$(g++ -std=c++98 -std=c++11 -m32 -m64 -O0 -O1 -g3 -g0 \
-Wformat -Wno-format -o wrong -o right main.cpp 2>&1)]"
[]
它不输出程序 wrong
:
$ ./wrong
bash: ./wrong: No such file or directory
它确实输出了一个程序right
:
$ ./right
C++11
-1713064076
这告诉我们它是用C++11
编译的,而不是C++98
。
由垃圾-1713064076
暴露出的错误没有被诊断,因为生效的是-Wno-format
而不是-Wformat
。
这是一个64位可执行文件,而不是32位的:
$ file right
right: ELF 64-bit LSB shared object, x86-64 ...
它被优化为-O1
,而不是-O0
,因为:
$ "[$(nm -C right | grep str)]"
[]
显示本地符号str
不在符号表中。
并且它不包含调试信息:
echo "[$(readelf --debug-dump right)]"
[]
-g0
,而不是-g3
。git
源代码控制在https://github.com/gcc-mirror/gcc获取。gcc/gcc/c-family/c-opts.c
中的函数。/* Handle switch SCODE with argument ARG. VALUE is true, unless no-
form of an -f or -W option was given. Returns false if the switch was
invalid, true if valid. Use HANDLERS in recursive handle_option calls. */
bool
c_common_handle_option (size_t scode, const char *arg, int value,
int kind, location_t loc,
const struct cl_option_handlers *handlers);
这本质上是一个简单的开关阶梯,枚举了scode
的选项设置——对于选项-std=c++11
,它是OPT_std_c__11
——并且毫不含糊地表明,它会将一个-std
选项设置放入到先前生效的任何设置中。你可以查看除了master
之外的其他分支(gcc-{5|6|7}-branch
),得出相同的结论。
在GCC构建系统脚本中,经常会发现依赖于通过附加新设置来覆盖选项设置的有效性。法律上,这通常依靠未记录的行为,但是GCC取最后解析的互斥选项设置的设置的可能性比俄罗斯加入北约更大。