使用g++编译时,默认使用哪种C++标准?

pgccezyw  于 2022-12-15  发布在  其他
关注(0)|答案(9)|浏览(390)

我有一段代码,如下所示:假设它位于一个名为example.cpp的文件中

#include <fstream>
#include <string> // line added after edit for clarity

int main() {
    std::string filename = "input.txt";
    std::ifstream in(filename);

    return 0;
}

在windows上,如果我在cmd中输入命令g++ example.cpp,它将失败。这是一个很长的错误列表,我认为主要是由于链接器抱怨无法从string转换为const char*
但是如果我使用一个额外的参数来运行编译器:g++ -std=c++17 example.cpp,它将编译和工作正常,没有任何问题。
当我运行前一个命令时会发生什么?我猜会调用C++编译器的默认标准版本,但我不知道是哪一个?作为程序员/开发人员,我应该总是使用带有额外参数的后一个命令吗?

euoag5mw

euoag5mw1#

如果您的g++版本高于4.7,我想您可以找到默认版本的C++标准支持如下:

g++ -dM -E -x c++  /dev/null | grep -F __cplusplus

我机器上的一个例子:

mburr@mint17 ~ $ g++ --version | head -1
g++ (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4
mburr@mint17 ~ $ g++ -dM -E -x c++  /dev/null | grep -F __cplusplus
#define __cplusplus 199711L

参考文献:

7tofc5zh

7tofc5zh2#

g手册页实际上告诉了C代码的默认标准是什么。
使用以下脚本显示相关部件:

man g++ | col -b | grep -B 1 -e '-std.* default'

例如,在RHEL 6 g++(GCC)4.4.7 20120313(红帽4.4.7-23)中,输出:

gnu++98
           GNU dialect of -std=c++98.  This is the default for C++ code.

而在Fedora 28 g++(GCC)8.1.1 20180502(红帽8.1.1-1)中,输出:

gnu++1y
           GNU dialect of -std=c++14.  This is the default for C++ code.  The name gnu++1y is deprecated.
wlp8pajw

wlp8pajw3#

您也可以使用gdb进行检查

  1. $ g++ example.cpp -g使用-g标志编译程序以生成调试信息
  2. $ gdb a.out使用gdb调试程序
  3. (gdb) b main在main中放置断点
  4. (gdb) run运行程序(将在断点处暂停)
  5. (gdb) info source
    打印类似于以下内容的内容:
Current source file is example.cpp
Compilation directory is /home/xxx/cpp
Located in /home/xxx/cpp/example.cpp
Contains 7 lines.
Source language is c++.
Producer is GNU C++14 6.3.0 20170516 -mtune=generic -march=x86-64 -g.
Compiled with DWARF 2 debugging format.
Does not include preprocessor macro info.

编译器使用的标准有:Producer is GNU C++14
例如,如果你使用-std=c++11重新编译你的程序,gdb会检测到它:Producer is GNU C++11

dvtswwa3

dvtswwa34#

我相信通过查看手册页(至少对于g++)就可以知道:
-std的描述下,手册页列出了所有的C++标准,包括GNU方言。在一个特定的标准下,它被相当不显眼地声明为This is the default for C++ code.(对于C标准有一个类似的声明:This is the default for C code.)。
例如,对于g++/gcc version 5.4.0,它列在gnu++98/gnu++03下,而对于g++/gcc version 6.4.0,它列在gnu++14下。

zpgglvta

zpgglvta5#

我猜会调用默认版本的C++编译器,但我不知道是哪个?
这只能通过阅读特定编译器版本的文档来猜测。
如果使用的是 * 最新的 * GCC,我建议首先通过运行以下命令来了解您使用的是什么版本

g++ -v

g++ --version

然后参考GCC特定发行版的版本。例如,对于GCC 7,请读取GCC 7 changes
或者,运行

g++ -dumpspecs

并解密默认的所谓spec file
顺便说一句,你可以通过编码来确保(例如在一些公共头文件中)C至少是C17

#if __cplusplus < 201412L
 #error expecting C++17 standard
 #endif

我建议你这么做。
实际上,把C98和C 17想象成两种不同的语言(比如Ocaml4和C11)。要求你的用户有一个编译器支持一些定义的语言标准(比如C11),而不是一些特定版本的GCC。也可以阅读关于package managers的内容。

nvbavucw

nvbavucw6#

man g++ | grep "This is the default for C++ code"

kupeojn6

kupeojn67#

在命令shell中输入g++ --version将显示编译器的版本,并从中推断出默认标准,因此您不能直接判断,但可以通过一些努力来“推断”它。
编译器被 * 假定 * 为#define__cplusplus,这可以用来提取它们声称在编译时实现的标准;但很多人还没有这么做。
(And别忘了包含所有你需要的C标准库头文件:例如,std::string的头文件在哪里?不要依赖于您的C标准库实现自动包含其他头文件-这样做就不是在编写可移植C++。

5n0oy7gb

5n0oy7gb8#

您的问题是特定于gnu编译器的,所以最好适当地标记它,而不仅仅是C和C11。
您的代码将使用任何兼容C11及更高版本的编译器(和关联库)进行编译。
原因是C
11引入了一个接受const std::string &std::ifstream构造函数。在C11之前,std::string不能被传递,并且在你的代码中必须传递filename.c_str()而不是filename
根据gnu的信息,https://gcc.gnu.org/projects/cxx-status.html#cxx11,gcc.4.8.1是第一个完全支持C
11的版本。在命令行g++ -v将提示g++告诉您它的版本号。
如果你深入研究文档,你可能会发现哪个版本/子版本最先支持了足够的特性来编译你的代码,但是这样的版本只支持C11的一些特性,而不支持其他特性。
由于windows没有随g
一起发布,你将拥有别人(你?)选择安装的任何版本,你的windows版本没有默认的g++版本。

am46iovg

am46iovg9#

C和C的默认语言标准在GCC手册中有详细说明。你可以在下面找到:
浏览到https://gcc.gnu.org/onlinedocs/
选择您感兴趣的GCC版本的GCC #.## Manual链接,例如GCC 7.5.0:
https://gcc.gnu.org/onlinedocs/gcc-7.5.0/gcc/
单击主题链接GCC支持的语言标准,然后单击主题** C
(或C语言**)。这两个主题中的任何一个主题都将包含如下句子:
如果没有给出 C++ 方言选项,则缺省值为-std=gnu++14。
如果没有给出C语言方言选项,则缺省值为-std= gnu 11。
以上两个示例适用于GCC 7.5.0。

相关问题