如何查找我的当前编译器标准,例如是否为C90等。

44

我正在使用 Linux 计算机。有没有系统命令可以查找我正在使用的 C 编译器所遵循的标准?

7个回答

38

这取决于编译器,我假设你正在使用的是GCC。
你可以使用以下方法检查编译器定义的宏:

gcc -dM -E - < /dev/null

请查看有关标志的手册,特别是:这里

###__STDC_VERSION__###

该宏扩展到C标准版本号,为一个长整型常量,其形式为yyyymmL,其中yyyy和mm是标准版本的年份和月份。这表示编译器符合哪个版本的C标准。与__STDC__一样,这不一定准确地反映了整个实现,除非使用GCC的GNU CPP。

值199409L表示1989 C标准作为1994年修订版,这是当前默认值;值199901L表示C标准的1999年修订版。对1999年修订版的支持尚未完成。

如果使用-traditional-cpp选项,则未定义此宏,编译C++或Objective-C时也未定义此宏。

这个网站上,您可以找到很多关于这方面的信息。请参阅此处的表格。


18

您还可以使用标准宏在代码中进行测试,例如(最初来自同名的sourceforge项目):

#if defined(__STDC__)
# define PREDEF_STANDARD_C_1989
# if defined(__STDC_VERSION__)
#  define PREDEF_STANDARD_C_1990
#  if (__STDC_VERSION__ >= 199409L)
#   define PREDEF_STANDARD_C_1994
#  endif
#  if (__STDC_VERSION__ >= 199901L)
#   define PREDEF_STANDARD_C_1999
#  endif
#  if (__STDC_VERSION__ >= 201710L)
#   define PREDEF_STANDARD_C_2018
#  endif
# endif
#endif

如果你想从命令行检查这个,你可以选择一个(例如c89)并检查最小程序的返回值:

echo -e "#ifdef __STDC__\n#error\n#endif"|gcc -xc -c - > /dev/null 2>&1; test $? -eq 0  || echo "c89

4
你可以在代码中加入 STDC_VERSION >= 201112L 条件以支持2011年的C标准。 - m0j0
2
谢谢你提醒我并给出建议。 - Flexo
1
查看C11的__STDC_VERSION__值是多少也很有用。 - chux - Reinstate Monica
2
使用 gcc -std=c90 编译时,宏 __STDC_VERSION__ 未被定义。此外,除非我弄错了,c89 和 c90 是相同的标准...是吗? - einpoklum

7

在编译时,检查预处理器宏:

  • __ANSI__
  • __STDC__
  • __STDC_VERSION__ >= 199901L 代表 c99

6
在 C 语言的任何版本中都没有叫做“__ANSI__”的东西。 - Lundin

5
您可能拥有gcc,这种情况下,您可以在编译时指定标准,例如:
$ gcc -Wall -std=c89 foo.c -o foo

或者:

$ gcc -Wall -std=c99 foo.c -o foo

类型:

$ man gcc

了解完整详情,请查看。


1
错误:"... 而不是如何定义 ..." - Tarantula
1
@Tarantula:谢谢,是的,你可能有一点道理。我假设OP不知道你可以控制使用的标准,因此给出了我的答案,但也许这是一个错误的假设。 - Paul R

5

为确定编译器从命令行支持的C版本,请键入:

gcc -dM -E - < /dev/null | grep "__STDC_"

使用您想要检查的编译器替换gcc。

如果编译器支持C89(也称为ANSI C)或ISO C90,则根据标准,您将看到__STDC__定义为1。(但有时__STDC__设置为其他非零值)。 C89与C90相同。 C89由ANSI批准。 一年后,ISO批准了ANSI标准。 ISO标准称为C90。

ISO C90标准已被修改,非正式称为C95。(有时也称为C94。但C95更常用)。 ISO还批准了C99,C11(2011年)和C17(2017年)。

如果编译器支持C95或更高版本,您将看到__STDC_VERSION__被定义。该值将根据版本而异。(例如,C99将使__STDC_VERSION__被定义为199901L的值)。请参见https://sourceforge.net/p/predef/wiki/Standards/ 如果您想在C程序中检查版本,请尝试使用此代码:
#include <stdio.h>
#include <math.h>       // Needed for INFINITY, HUGE_VAL, HUGE_VALF & HUGE_VALL
                        // constants (or macros)
#if !defined(__STDC__)
#   define __STDC__ 0
#endif

#if !defined(__STDC_VERSION__) 
#   define __STDC_VERSION__ 0
#endif


int main()
{
    if (!__STDC__ && !__STDC_VERSION__) printf("The C compiler does not comply with the C89 or later standard!\nIt likely complies with the 1978 K&R C standard (informally known as C78).\n");
    else if (__STDC_VERSION__ >= 201710L) printf("The C compiler complies with the C17 standard.\n");
    else if (__STDC_VERSION__ >= 201112L) printf("The C compiler complies with the C11 standard.\n");
    else if (__STDC_VERSION__ >= 199901L) printf("The C compiler complies with the C99 standard.\n");
    else if (__STDC_VERSION__ >= 199409L) printf("The C compiler complies with the amended C90 standard (also known as C95).\n");
    else if (__STDC__) printf("The C compiler complies with the ANSI C89 / ISO C90 standard.\n");
   
    puts("");
    if (__STDC__) printf("\"__STDC__\": %ld\n", __STDC_VERSION__);
    if (__STDC_VERSION__) printf("\"__STDC_VERSION__\": %ld\n\n", __STDC_VERSION__);
    
    puts("");
    if (__STDC_VERSION__ >= 199901L) printf(" INFINITY (added in C99): %f\n", INFINITY );    // Also works with %lf and %Lf
    if (__STDC_VERSION__ >= 199901L) printf("-INFINITY (added in C99): %f\n", -INFINITY );   // Also works with %lf and %Lf
    
    puts("");
    if (__STDC_VERSION__ >= 199901L) printf(" HUGE_VALF (added in C99): %f\n", HUGE_VALF );
    if (__STDC_VERSION__ >= 199901L) printf("-HUGE_VALF (added in C99): %f\n", -HUGE_VALF );
    
    puts("");
    if (__STDC__) printf(" HUGE_VAL (added in C89 (ANSI) which is the same as C90 (ISO)): %lf\n", HUGE_VAL );
    if (__STDC__) printf("-HUGE_VAL (added in C89 (ANSI) which is the same as C90 (ISO)): %lf\n", -HUGE_VAL );

    puts("");
    if (__STDC_VERSION__ >= 199901L) printf(" HUGE_VALL (added in C99): %Lf\n", HUGE_VALL );
    if (__STDC_VERSION__ >= 199901L) printf("-HUGE_VALL (added in C99): %Lf\n", -HUGE_VALL );

    return 0;
}

以下是使用www.onlinegdb.com的C编译器运行此程序的输出结果:
The C compiler complies with the C99 standard.

"__STDC__": 199901
"__STDC_VERSION__": 199901


 INFINITY (added in C99): inf
-INFINITY (added in C99): -inf

 HUGE_VALF (added in C99): inf
-HUGE_VALF (added in C99): -inf

 HUGE_VAL (added in C89 (ANSI) which is the same as C90 (ISO)): inf
-HUGE_VAL (added in C89 (ANSI) which is the same as C90 (ISO)): -inf

 HUGE_VALL (added in C99): inf
-HUGE_VALL (added in C99): -inf

1
如果你的C编译器是gcc,你可以使用-std选项来指定要遵循的C标准。默认值为gnu89。没有一般性的系统命令可以确定任何给定编译器的标准。你需要检查文档。

1
您可以使用标准宏编写一个小程序来检查。 - Flexo
1
不错,是的。我刚写了一个小测试,但是__STDC_VERSION__在gcc默认标准(gnu89)下未定义。 - ciaron

0
我认为Tarantula的答案并不完全正确 - 因为c89和c90是相同的标准(至少被clang和gcc这样处理),并且没有定义__STDC_VERSION__。
所以也许可以这样说:
#if defined(__STDC__)
#  if defined(__STDC_VERSION__)
#    if (__STDC_VERSION__ >= 201710L)
#      define C_LANGUAGE_STANDARD 2018
#    elif (__STDC_VERSION__ >= 201112L)
#      define C_LANGUAGE_STANDARD 2011
#    elif (__STDC_VERSION__ >= 199901L)
#      define C_LANGUAGE_STANDARD 1999
#    elif (__STDC_VERSION__ >= 199409L)
#      define C_LANGUAGE_STANDARD 1995
#    endif
#  else
#      define C_LANGUAGE_STANDARD 1990
#  endif
#else
#      define C_LANGUAGE_STANDARD 1972
#endif

更合适呢?


你是正确的。C89和C90是相同的标准。C89由ANSI批准,而C90由ISO批准。两者都只定义了__STDC__。C89和C90都没有使用__STDC_VERSION__。请参见https://sourceforge.net/p/predef/wiki/Standards/。 - RobK
技术上来说,你是正确的。并没有C94或C95标准。有一个修订版的C90标准,非正式地称为C95。如果编译器符合C95,__STDC_VERSION__将被设置为199409L。请参见https://sourceforge.net/p/predef/wiki/Standards/。(此网站将C95称为C94,有些人这样做。但C95更常用)。 - RobK
@RobK:有没有编译器可以这样编译? - einpoklum
@einpoklim:是的!在1995年至1999年期间,有一些编译器使用C95进行编译。即使在今天,如果您使用选项-std=iso9899:199409,gcc也会按照C95标准进行编译。请参见https://gcc.gnu.org/onlinedocs/gcc/Standards.html。但我不知道为什么今天还会有人使用C95。 C99只是在C95基础上增加了很多新功能。因此,C99编译器应该能够很好地编译按照C95编写的代码。 - RobK

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