为什么这个C代码可以在C99中编译?我应该读什么来了解更多?
我不能发布,除非我添加更多的文本所以这里有一些无意义的文本因为我认为没有什么可以说的
$ cat m.c
#include <stdio.h>
#include <time.h>
int main() {
struct timespec time;
int res = clock_gettime(CLOCK_REALTIME, &time);
printf("%d %ld %ldn", res, time.tv_sec, time.tv_nsec);
return 0;
}
$ clang m.c && ./a.out && rm ./a.out
0 1631386905 774654955
$ clang -std=c99 m.c && ./a.out && rm ./a.out
m.c:4:18: error: variable has incomplete type 'struct timespec'
struct timespec time;
^
m.c:4:9: note: forward declaration of 'struct timespec'
struct timespec time;
^
m.c:5:12: warning: implicit declaration of function 'clock_gettime' is invalid in C99 [-Wimplicit-function-declaration]
int res = clock_gettime(CLOCK_REALTIME, &time);
^
m.c:5:26: error: use of undeclared identifier 'CLOCK_REALTIME'
int res = clock_gettime(CLOCK_REALTIME, &time);
^
1 warning and 2 errors generated.
这是因为使用-std=c99
选项定义了一个宏,导致clock_gettime
的声明被隐藏。
GNU C库可以公开其函数的不同版本,或者完全隐藏它们,这取决于用户代码的期望。用户代码通过定义某些特定命名的宏(称为特性测试宏,尽管这有点用词不当)来声明这些期望,这些宏具有GNU C库头文件识别的预先确定的值。一个这样的宏是__STRICT_ANSI__
,如果使用了-std=cXX
中的任何一个选项,它是隐式定义的。
引用feature_test_macros(7)
:
当使用
__STRICT_ANSI__
-std=c99
或-ansi
标志调用时,该宏由gcc(1)
隐式定义。[…]
如果显式定义了
__STRICT_ANSI__
、_ISOC99_SOURCE
、_ISOC11_SOURCE
(自glibc 2.18起)、_POSIX_SOURCE
、_POSIX_C_SOURCE
、_XOPEN_SOURCE
、_XOPEN_SOURCE_EXTENDED
(glibc 2.11及更早版本)、_BSD_SOURCE
(glibc 2.19及更早版本)、_SVID_SOURCE
(glibc 2.19及更早版本)中的任何一个,则默认不定义_BSD_SOURCE
、_SVID_SOURCE
和_DEFAULT_SOURCE
。
使用-std=gnuXX
选项代替-std=cXX
不会导致__STRICT_ANSI__
被定义;它还支持对C语言的GNU扩展。如果您想禁用这些语言扩展,您可以将#define _DEFAULT_SOURCE 1
放在文件的最顶部,以公开C库否则会公开的所有符号(或者可能是另一个功能测试宏来调整库接口以满足您的喜好)。一个显式的特性测试宏将优先于__STRICT_ANSI__
。