当前GCC的默认C -std标准版本是什么(特别是在Ubuntu上)?

80

当我要求查看cc的当前版本时,我得到了这个。

$ cc --version
cc (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ 

我想了解正在使用的是c89、c90、c99还是c11中的哪一个。


22
C89和C90是完全相同的语言。1989年的ANSI C标准和1990年的ISO C标准只有一些(非规范性的)介绍材料和章节重新编号方面有所不同。C99和C11标准最初由ISO发布,后来被ANSI采用。(“ANSI C”一词仍然倾向于指代C89/C90,尽管官方上C11是当前的ANSI标准。) - Keith Thompson
7个回答

106
这在gcc手册中有详细解释,可以通过输入info gcc或在线here(如果已安装)获得。当前手册的相关部分在here,但可能与您使用的版本相对应也可能不相对应。
自2013年发布此答案以来,其中一些信息已更改,并将继续更改。如果您在2023年左右阅读此内容,则当前版本可能是-std=gnu17(带有GNU特定扩展的C17;C17是对C11的轻微更新)。您应该检查所使用版本的文档。C23标准尚未发布,但应该很快就会发布。我无法预测gcc何时将切换到-std=gnu23作为其默认设置。如果您在遥远的未来阅读此内容,请告诉我们事情的进展情况。

gcc 3.0 到 4.9.4 版本默认使用 -std=gnu89-std=gnu90
gcc 5.5 到 10.4 版本默认使用 -std=gnu11(虽然跳过了 -std=gnu99,但仍可指定)。
gcc 11.3 和 12.2 版本默认使用 std=gnu17


默认情况下,gcc不符合任何ANSI/ISO C标准。当前的默认设置等同于-std=gnu17,这是带有GNU特定扩展的2017年标准。(一些语言标准所要求的诊断未被发出。)早期版本的gcc默认为-std=gnu90-std=gnu11
如果您想要标准一致性,可以使用以下任何一个:
-std=c90 -pedantic
-std=c99 -pedantic
-std=c11 -pedantic
-std=c17 -pedantic

-std=c90可以拼写为-ansi-std=c89-std=iso9899:1990

-std=iso9899:199409支持C90标准加上1995年的修正案,增加了一些小的功能(这些功能也都在C99中)。

-std=c99可以拼写为-std=c9x-std=iso9899:1999(在标准发布之前使用了名称)。C99支持不完全,但接近于完整。

"-std=c11"也可以写成"-std=c0x"或"-std=iso9899:2011"(在最终标准发布之前使用了名称"c0x",错误地假定"x"不会超过9)。C11支持也不完整;当前状态在此处概述
"-pedantic"选项会导致gcc打印违反约束和语法规则所需的诊断信息。在某些情况下,这些诊断信息仅仅是警告--并且没有简单的方法来区分那些警告和其他不被语言要求的警告。将"-pedantic"替换为"-pedantic-errors",以使gcc将语言违规视为致命错误。
标准的简要历史:
  • C89是第一个官方的C标准,由ANSI在1989年发布。
  • C90是标准的ISO版本,描述了与C89完全相同的语言。ANSI正式采用了ISO的标准版本。有两个技术勘误,纠正了一些错误。
  • C95是对C90的修正案,增加了一些功能,主要是双字符和宽字符支持。据我所知,合并版本从未发布过。
  • C99是由ISO于1999年发布的。有三个技术勘误。
  • C11是由ISO于2011年发布的。有一个技术勘误,修正了__STDC_VERSION____STDC_LIB_EXT1__的定义。
  • C17是由ISO于2017年发布的,只是对C11的轻微更新。
  • C23将于2023年发布。(我写这篇文章时,它已接近完成,但文件仍在编辑中。)

ANSI没有发布自己的1999年或之后的标准版本,而是采用了ISO标准。

N1256是C99标准的免费草案,其中包括3个技术勘误合并在内。

N1570是C11标准的免费草案。它与已发布的C11标准有一些小的差异,还有一个技术勘误。更多详细信息,请参见这个问题我的答案


6
关于N1570和C11的差异,请参见https://dev59.com/i2oy5IYBdhLWcg3wUcb_。它们没有区别:他们甚至忘记更新`__STDC_VERSION__`和`__STDC_LIB_EXT1__`!(这在Cor 1:2012中得到了修复;请参见stackoverflow.com/q/13914050/95580。) - J. C. Salomon
1
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Keith Thompson
1
@ChefGladiator 目前仍然是“C2X”。不确定2023年是否是最初的预定年份,但我没有看到他们特别瞄准那一年的迹象。 - AJM
1
@ChefGladiator GCC 9.4.0(Ubuntu默认)的默认设置是gnu11。GCC 12.1.0的默认设置为gnu17。(请参见https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gcc/Standards.html#C-Language) - c21253
1
@Hydrargyrum 不算最新,因为gcc 13还没有发布,但它应该很快就会发布了。 - Keith Thompson
显示剩余3条评论

38

对于gcc6,info gcc中包含有用信息;对于gcc5,请参考https://gcc.gnu.org/onlinedocs/gcc-5.4.0/gcc/Standards.html#Standards

gcc版本6.3.1 - 10.1.0

2.1 C Language
==============
 The default, if no C language dialect options are given, is
'-std=gnu11'.

2.2 C++ Language
================
 The default, if no C++ language dialect options are given, is
'-std=gnu++14'.

gcc版本5.4.0

2.1 C Language
==============
The default, if no C language dialect options are given, is -std=gnu11

2.2 C++ Language
================
The default, if no C++ language dialect options are given, is -std=gnu++98

对于C语言,默认模式仍为std=gnu11,但对于C++语言,它已经从std=gnu++98升级到了std=gnu++14


5
这回答了这个问题。 - raj_gt1
1
看起来gcc 10.2是gnu17 - Amomum

20

最小化测试程序

如果您想在不阅读任何手册的情况下通过实证找出答案。

c.c

#include <stdio.h>

int main(void) {
#ifdef __STDC_VERSION__
    printf("__STDC_VERSION__ = %ld \n", __STDC_VERSION__);
#endif
#ifdef __STRICT_ANSI__
    puts("__STRICT_ANSI__");
#endif
    return 0;
}

使用以下测试:

#!/usr/bin/env bash
for std in c89 c99 c11 c17 gnu89 gnu99 gnu11 gnu17; do
  echo $std
  gcc -std=$std -o c.out c.c
  ./c.out
  echo
done
echo default
gcc -o c.out c.c
./c.out

结果:

c89
__STRICT_ANSI__

c99
__STDC_VERSION__ = 199901
__STRICT_ANSI__

c11
__STDC_VERSION__ = 201112
__STRICT_ANSI__

c17
__STDC_VERSION__ = 201710
__STRICT_ANSI__

gnu89

gnu99
__STDC_VERSION__ = 199901

gnu11
__STDC_VERSION__ = 201112

gnu17
__STDC_VERSION__ = 201710

default
__STDC_VERSION__ = 201710

结论: 默认情况下使用 gnu17:

关于-std=gnu*-std=c*的解释,请参见:什么是-std=c++11和-std=gnu++11之间的区别?

C++

main.cpp

#include <iostream>

int main(void) {
#ifdef __cplusplus
    std::cout << __cplusplus << std::endl;
#endif
#ifdef __STRICT_ANSI__
    std::cout << "__STRICT_ANSI__" << std::endl;
#endif
    return 0;
}

Test with:

#!/usr/bin/env bash
for std in c++98 c++11 c++14 c++17 gnu++98 gnu++11 gnu++14 gnu++17; do
  echo $std
  g++ -std=$std -o cpp.out cpp.cpp
  ./cpp.out
  echo
done
echo default
g++ -o cpp.out cpp.cpp
./cpp.out

结果:

c++98
199711
__STRICT_ANSI__

c++11
201103
__STRICT_ANSI__

c++14
201402
__STRICT_ANSI__

c++17
201703
__STRICT_ANSI__

gnu++98
199711

gnu++11
201103

gnu++14
201402

gnu++17
201703

default
201402

结论: 默认使用gnu++14:

  • __cplusplus: C++标准定义的宏,包括C++98及其以后版本

在Ubuntu 18.10、GCC 8.2.0上进行了测试。GitHub源代码


gnu17c17有什么区别?它们之间有很大的差异吗? - Ravi Raj
@RaviRaj gnu*c* 加上所有 GNU 语言扩展,其中可能有几十个,c* 是严格的 ANSI 标准,另请参见:https://dev59.com/vWkv5IYBdhLWcg3waAJT - Ciro Santilli OurBigBook.com

3

我找到了一种查询C++版本的方法,并将其适用于C语言:

gcc -dM -E -x c  /dev/null | grep -F __STDC_VERSION__

3

第一行会显示你的GCC版本(4.7.2)

(Ubuntu/Linaro 4.7.2-2ubuntu1)4.7.2

编译代码时,您可以通过添加-std=c99-std=c99来指定您想要使用哪个C/C++修订版...

请注意,默认情况下使用gnu89


1
请注意,gcc的-std选项不能用于“沙盒”编译器以不支持来自后续版本标准C的结构。这是无论是否使用-pedantic都是如此。
您不能依赖于gcc -std=c89 -pedantic在尝试使用一些C99代码结构进行编译时提供错误或警告。在某些情况下,它会,而在其他情况下则不会。例如,它将愉快地编译使用printf()调用中的%zu格式说明符的代码,即使它直到C99才被添加。

对于这个特定的例子,是因为printf是一个库函数,从技术上讲,编译器并不关心它。虽然许多编译器确实有一个针对格式字符串的lint检查,但在这里诊断问题并不是必需的。 - Zan Lynx

-2

默认的gcc命令是GNU方言的ISO C90(包括一些C99特性)。这是C代码的默认设置。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接