假设使用
运行g++
是否安全
g++ -std=c++98 -std=c++11 ...
将使用C ++ 11编译?我还没有在documentation中找到明确的确认信息,但我看到-O
标记就是这样的。
答案 0 :(得分:6)
GCC manual没有声明
指定的任何互斥-std=...
选项的最后一个生效。第一次出现
或最后一次出现是唯一的选择。有很多
GCC标志从有限集中采用互斥的替代值 - 相互作用
独家,至少模数翻译单位的语言。我们简称为互斥选项。
对于它的记录,最后一个设置生效,这似乎是一个随机的罕见。它是
记录了-O
选项,如您所述,也可能是相互排斥的警告选项的一般术语
其他。从未记录多个设置的第一个生效,因为
它永远不会成真。
文档在历史惯例上倾斜 - 具有不完美的一致性 unix-like操作系统中的命令用法。如果命令接受互斥锁选项 然后该选项的最后一次出现生效。如果命令是 - 异常 - 只有在第一次出现选项时才会采取行动,那么这将是一个错误 接受后续发生的命令:它应该给出一个使用错误。
这是习惯和做法。自定义使用工具来编写脚本 尊重它,例如脚本可以调用传递某些默认设置的工具 互斥选项,但允许用户通过脚本参数覆盖该设置, 其值可以简单地附加到默认调用。
如果没有正式的GCC文档,您可能会得到 通过尝试找到任何不是的GCC互斥选项来保证安全 最后一次出现的情况。这是一个刺:
我将编译并链接此程序:
<强>的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
。
由于GCC是开源软件,另一种解决疑虑的方法
关于它对C程序员可用的行为,至少,
是检查相关的源代码,可通过git
source-control at获得
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
枚举的选项设置的简单切换梯形图
选项OPT_std_c__11
为-std=c++11
- 毫无疑问
无论先前生效的设置如何,都会将-std
选项设置生效。您可以查看master
以外的分支
(gcc-{5|6|7}-branch
)得出同样的结论。
找到依赖于其有效性的GCC构建系统脚本并不罕见 通过附加新设置覆盖选项设置。在法律上,这个 通常依靠无证件行为,但有一个更好的 俄罗斯加入北约的机会比GCC不再采取最后的设定 它解析互斥锁选项。