我正在阅读getaddrinfo的手册页并尝试按照示例代码进行操作,但它没有编译:
// test.c
#include <netdb.h>
void f() {
struct addrinfo t;
}
两个都有clang:
$ clang -std=c11 test.c
test.c:10:21: error: variable has incomplete type 'struct addrinfo'
struct addrinfo t;
^
test.c:10:12: note: forward declaration of 'struct addrinfo'
struct addrinfo t;
^
1 error generated.
和gcc:
$ gcc -std=c11 test.c
test.c: In function ‘f’:
test.c:10:21: error: storage size of ‘t’ isn’t known
struct addrinfo t;
^
经过一番挖掘后,我发现glibc headers有一个预处理器指令,可以保护&#34; (这是正确的术语吗?)struct
被定义,所以我想知道:
#ifdef __USE_XOPEN2K
和others don't?什么用于?为什么它会从__USE_POSIX改变?__USE_XOPEN2K
,-std=gnu89
,-std=gnu90
来定义-std=gnu99
,而不是-ansi
,-std=c89
,{{1} },-std=c90
和-std=c99
?-std=c11
或使用-std=gnuXX
?答案 0 :(得分:9)
简短的回答,如果你使用不属于标准C的API的glibc(任何与UNIX相关的东西),只需使用-std=gnuXX
- 这将启用couple of features in the glibc。 docs
答案很长:
这是一个复杂的问题,C编程语言和Unix操作系统都很陈旧,并且有很多包袱;这是我尝试理解所有这些。
有一种C编程语言。该语言出现在1972年,但直到1989年批准第一个ANSI C时才开始标准化。目前有C编程语言的这些规范:
C标准有一个真正的limited scope,它提供语法,语义和some library headers and functions。规范(c99和c11)包含编译器应公开的一些预定义宏,这些宏用于表示符合标准,因此程序可以使用旧规范中没有的新功能。 ;但是,源代码可以使用宏来删除功能。
除了C编程语言规范之外,还有一些UNIX specifications。试图缩短long story和错综复杂的历史,忽略商标和法律问题的问题:
一开始UNIX没有规范,它的来源被非法复制和修改,结果是long list个UNIX变体,其中一些发明了不兼容或冲突的API,如BSD&#tty socket和SVR3 termio。一段时间后,工作组成立,以使操作系统标准化:
这些小组的工作可以用这个不完整的时间表来描述:
首字母缩略词是:
好的,现在GCC和glibc需要编译和链接任何用这些标准开发的C程序,glibc docs说:
如果使用“
gcc -ansi
”编译程序,则只能获得ISO C库功能,除非您通过定义一个或多个功能宏明确请求其他功能[...]。您应该使用源代码文件顶部的“#define
”预处理程序指令来定义这些宏。这些指令必须在系统头文件的任何#include之前[...]。该系统的存在是为了使库符合多种标准。
GCC关于language's dialects的文档声明如下:
-ansi
相当于-std=c90
[...]。这会关闭GCC的某些功能,这些功能与 ISO C90 (编译C代码时)(例如asm和typeof关键字)以及预定义的宏(例如unix和vax)不兼容,这些宏标识了系统的类型正在使用。对于C代码,-std=‘c89’
与-ansi
相同。
还有关于standard libraries的文档:
如果您需要符合标准的库,那么您需要找到一个,因为GCC没有提供。 GNU C库(称为glibc)为GNU / Linux和基于HURD的GNU系统提供ISO C,POSIX,BSD,SystemV和X / Open兼容性;
有用的链接: