为什么仅在定义__USE_XOPEN2K时才定义struct addrinfo?

时间:2015-10-12 08:09:16

标签: c gcc clang

我正在阅读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被定义,所以我想知道:

  • 为什么glibc使用#ifdef __USE_XOPEN2Kothers don't?什么用于?为什么它会从__USE_POSIX改变?
  • 为什么clang和gcc使用__USE_XOPEN2K-std=gnu89-std=gnu90来定义-std=gnu99,而不是-ansi-std=c89,{{1} },-std=c90-std=c99
  • 我应该使用什么来解决错误?使用-std=c11或使用-std=gnuXX

1 个答案:

答案 0 :(得分:9)

简短的回答,如果你使用不属于标准C的API的glibc(任何与UNIX相关的东西),只需使用-std=gnuXX - 这将启用couple of features in the glibcdocs

答案很长:

这是一个复杂的问题,C编程语言和Unix操作系统都很陈旧,并且有很多包袱;这是我尝试理解所有这些。

有一种C编程语言。该语言出现在1972年,但直到1989年批准第一个ANSI C时才开始标准化。目前有C编程语言的这些规范:

  • 1989 称为 ANSI C C89 [X3.159-1989]。
  • 1990 称为 ISO C C90 [ISO / IEC 9899:1990]
  • 1995 称为 AMD1 C94 C95 [ISO / IEC 9899:1990 / AMD 1 :1995]
  • 1999 称为 C99 [ISO / IEC 9899:1999]
  • 2011 称为 C11 C1X [ISO / IEC 9899:2011]

C标准有一个真正的limited scope,它提供语法,语义和some library headers and functions。规范(c99c11)包含编译器应公开的一些预定义宏,这些宏用于表示符合标准,因此程序可以使用旧规范中没有的新功能。 ;但是,源代码可以使用宏来删除功能。

除了C编程语言规范之外,还有一些UNIX specifications。试图缩短long story和错综复杂的历史,忽略商标和法律问题的问题:

一开始UNIX没有规范,它的来源被非法复制和修改,结果是long list个UNIX变体,其中一些发明了不兼容或冲突的API,如BSD&#tty socket和SVR3 termio。一段时间后,工作组成立,以使操作系统标准化:

  • 1983 Uniforum 也知道 / usr / group 创建了第一个名为核心UNIX系统的标准化
  • 1985 AT&amp; T 拥有 System V接口定义 SVID
  • 1984 The Open Group 也知道 X / Open 创建了 X / Open Portability Guide XPG
  • 1985 IEEE 1003 组已创建,他们创建了 POSIX 标准

这些小组的工作可以用这个不完整的时间表来描述:

  • 1983 Uniforum 创建核心UNIX系统 UDS 83 [Uniforum 1983草案标准]
  • 1985 SVID 取代 UDS 83
  • 使用 SVR2 4.2BSD (POSIX plus套接字)的API
  • 1985 XPG1
  • 1987,1990,1992 XPG2 XPG3 XPG4
  • 1988 - 1995 构成 POSIX 标准的第一批文件( 1003.1 ,1003.2 *和 1003.4
  • 1997 SUSv2
  • 2004 POSIX:2004 SUSv3,2001版本的更新 [IEEE Std 1003.1-2004]
  • 2008 POSIX:2008 [IEEE Std 1003.1-2008]

首字母缩略词是:

  • SUS 是指单一UNIX规范
  • XPG 是指 X / Open Portability Guides
  • POSIX 是指可移植操作系统接口

好的,现在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兼容性;

有用的链接: