将多个-std开关传递给g ++

krl*_*mlr 5 gcc g++ options

假设g++与之一起运行是否安全

g++ -std=c++98 -std=c++11 ...
Run Code Online (Sandbox Code Playgroud)

将使用C++ 11编译?我没有在文档中找到明确的确认,但我看到-O标志就是这样的.

Mik*_*han 7

GCC手册并没有说明最后的互斥-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;
} 
Run Code Online (Sandbox Code Playgroud)

使用命令行:

g++ -std=c++98 -std=c++11 -m32 -m64 -O0 -O1 -g3 -g0 \
-Wformat -Wno-format -o wrong -o right main.cpp
Run Code Online (Sandbox Code Playgroud)

要求相互矛盾的选项对:

  • -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)]"
[]
Run Code Online (Sandbox Code Playgroud)

它不输出任何程序wrong:

$ ./wrong
bash: ./wrong: No such file or directory
Run Code Online (Sandbox Code Playgroud)

它输出一个程序right:

$ ./right
C++11
-1713064076
Run Code Online (Sandbox Code Playgroud)

它告诉我们它被编译为C++11,而不是C++98.

垃圾暴露的错误-1713064076没有被诊断出来,因为它 -Wno-format没有-Wformat生效.

它是64位,而不是32位可执行文件:

$ file right
right: ELF 64-bit LSB shared object, x86-64 ...
Run Code Online (Sandbox Code Playgroud)

它被优化了-O1,而不是-O0因为:

$ "[$(nm -C right | grep str)]"
[]
Run Code Online (Sandbox Code Playgroud)

显示本地符号str不在符号表中.

它不包含调试信息:

echo "[$(readelf --debug-dump right)]"
[]
Run Code Online (Sandbox Code Playgroud)

按照-g0,不是-g3.

由于GCC是开源软件,解决C程序员可用行为疑虑的另一种方法,至少是检查相关的源代码,可通过https://github.com/gcc-上的源代码git控制获得. 镜子/ 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);
Run Code Online (Sandbox Code Playgroud)

它本质上是一个简单的切换梯形图,其选项设置由scode- 枚举- OPT_std_c__11用于选项-std=c++11- 毫无疑问,-std无论先前生效的设置如何,它都会使选项设置生效.您可以使用相同的结论来查看除master (gcc-{5|6|7}-branch)之外的分支.

通过附加新设置,找到依赖于覆盖选项设置的有效性的GCC构建系统脚本并不罕见.从法律上讲,这通常是指无证行为,但俄罗斯加入北约的可能性要大于GCC不再采用其解析互斥选项的最后设置.