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

标签 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有一个预处理器指令来“保护”(这是正确的术语吗?)struct从被定义,所以我想知道:
  • 为什么 glibc 使用 #ifdef __USE_XOPEN2Kothers don't ?有什么用?为什么从 __USE_POSIX 变了?
  • 为什么clang和gcc定义__USE_XOPEN2K-std=gnu89 , -std=gnu90 , -std=gnu99但不是 -ansi , -std=c89 , -std=c90 , -std=c99-std=c11 ?
  • 我应该用什么来避免错误?使用 -std=gnuXX或使用 #define __USE_XOPEN2K ?
  • 最佳答案

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

    长答案:
    这是一个复杂的问题,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 套接字和 SVR3 termio。一段时间后,成立了工作组来标准化操作系统:
  • 1983 Uniforum 也称为/usr/group 创建了第一个名为核心 UNIX 系统的标准化
  • 1985 AT&T 拥有 System V 接口(interface)定义或 SVID
  • 1984 The Open Group 也称为 X/Open,创建了 X/Open 可移植性指南或 XPG,
  • 1985 IEEE 1003 小组创建,他们创建了 POSIX 标准

  • 这些小组的工作可以用这个不完整的时间表来描述:
  • 1983 Uniforum 创建了核心 UNIX 系统或 UDS 83 [Uniforum 1983 草案标准]
  • 1985 SVID 取代了 UDS 83
  • 1985 XPG1 带有来自 SVR2 和 4.2BSD 的 API(POSIX 加套接字)
  • 1987,1990,1992 XPG2、XPG3 和 XPG4
  • 1988 - 1995 构成 POSIX 标准的第一个文档(1003.1、1003.2* 和 1003.4)
  • 1997 SUSv2
  • 2004 POSIX:2004 或 SUSv3 , 2001 版本的更新
    [IEEE 标准 1003.1-2004]
  • 2008 POSIX:2008 [IEEE Std 1003.1-2008]

  • 缩写词是:
  • SUS 指 单 UNIX 规范
  • XPG 指 X/Open 便携性指南
  • POSIX 指的是 可移植操作系统接口(interface)

  • 好的,现在 GCC 和 glibc 需要编译和链接到任何使用这些标准开发的 C 程序,glibc docs说:

    If you compile your programs using ‘gcc -ansi’, you get only the ISO C library features, unless you explicitly request additional features by defining one or more of the feature macros [...]. You should define these macros by using ‘#define’ preprocessor directives at the top of your source code files. These directives must come before any #include of a system header file [...]. This system exists to allow the library to conform to multiple standards.


    GCC 关于 language's dialects 的文档声明如下:

    -ansi is equivalent to -std=c90 [...]. This turns off certain features of GCC that are incompatible with ISO C90 (when compiling C code), such as the asm and typeof keywords, and predefined macros such as unix and vax that identify the type of system you are using. -std=‘c89’ is the same as -ansi for C code.


    还有关于 standard libraries 的文档:

    If you need a standard-compliant library, then you need to find one, as GCC does not provide one. The GNU C library (called glibc) provides ISO C, POSIX, BSD, SystemV and X/Open compatibility for GNU/Linux and HURD-based GNU systems;


    有用的链接:
  • GCC Standards
  • iso-9899 wiki
  • 所以:Where can I find the C89/C90 standards in PDF format?
  • 关于c - 为什么 struct addrinfo 仅在定义了 __USE_XOPEN2K 时才定义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33076175/

    相关文章:

    c - 如何确定 C 结构中一个指针的元素数量

    c# - 从 CLI C++ 应用程序加载库内的 C# WPF 表单

    c++ - 不同编译器的不同输出 - C 和 C++

    c - c 中的矩阵乘法

    c++ - 返回 ARM NEON 下的 Z 标志

    c++ - Eclipse Cdt Indexer - 如何定位语法错误和未解析的名称

    C++11 lambdas 可以访问我的私有(private)成员。为什么?

    linux - 了解 ASAN 输出

    c - 为什么 Clang 会看到类型冲突?

    从终端进行 iPhone 静态代码分析未能找到丢失的 ivar 版本