我正在阅读getaddrinfo的手册页并尝试遵循示例代码,但它不能编译:
// test.c
#include <netdb.h>
void f() {
struct addrinfo t;
}
Run Code Online (Sandbox Code Playgroud)
两个都有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.
Run Code Online (Sandbox Code Playgroud)
和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;
^
Run Code Online (Sandbox Code Playgroud)
经过一番挖掘后,我发现glibc头文件有一个预处理器指令,可以"保护"(这是正确的术语吗?)struct
来定义,所以我想知道:
#ifdef __USE_XOPEN2K
而其他人不使用?什么用于?为什么它从__USE_POSIX改变了?__USE_XOPEN2K
有-std=gnu89
,-std=gnu90
,-std=gnu99
但不与-ansi
,-std=c89
,-std=c90
,-std=c99
和-std=c11
?-std=gnuXX
还是使用#define __USE_XOPEN2K
?简短的回答,如果你使用不属于标准C的API的glibc(任何与UNIX相关的东西),只需使用-std=gnuXX
- 这将启用glibc中的一些功能.文档
答案很长:
这是一个复杂的问题,C编程语言和Unix操作系统都很老旧,并且有很多包袱; 这是我尝试理解所有这一切.
有一种C编程语言.该语言出现在1972年,但直到1989年批准第一个ANSI C时才开始标准化.目前有这些C编程语言的规范:
C标准的范围非常有限,它提供了语法,语义和一些库头和函数.规范(c99和c11)包含一些编译器应该公开的预定义宏,这些宏用于表示符合标准,因此程序可以使用旧规范没有的新功能,但是没有宏源代码可用于删除功能.
除了C编程语言规范之外,还有几个UNIX规范.试图制作一个长篇故事和错综复杂的历史,忽略商标和法律问题的问题:
最初UNIX没有规范,它的来源被非法复制和修改,结果是一长串 UNIX变体,其中一些发明了不兼容或冲突的API,如BSD的tty socket和SVR3 termio.一段时间后,工作组成立以标准化操作系统:
这些小组的工作可以用这个不完整的时间表来描述:
首字母缩略词是:
好吧,现在GCC和glibc需要编译和链接任何用这些标准开发的C程序,glibc文档说:
如果使用'
gcc -ansi
' 编译程序,则只能获得ISO C库功能,除非您通过定义一个或多个功能宏明确请求其他功能[...].您应该使用#define
源代码文件顶部的' '预处理程序指令来定义这些宏.这些指令必须在系统头文件的任何#include之前[...].存在该系统以允许库符合多个标准.
海湾合作委员会关于语言方言的文件陈述如下:
-ansi
相当于-std=c90
[...].这将关闭GCC的某些功能,这些功能与ISO C90(编译C代码时)(例如asm和typeof关键字)以及预定义的宏(例如unix和vax)不兼容,这些宏标识了您正在使用的系统类型.-std=‘c89’
与-ansi
C代码相同.
还有关于标准库的文档:
如果您需要符合标准的库,那么您需要找到一个,因为GCC没有提供.GNU C库(称为glibc)为GNU/Linux和基于HURD的GNU系统提供ISO C,POSIX,BSD,SystemV和X/Open兼容性;
有用的链接: