c - GCC 4 中的 in6_addr

标签 c linux gcc

我看到如下代码:(我正在处理的项目中的旧代码)

#if __GNUC__ > 3
    .ipv6_addr = {.__in6_u = {.__u6_addr32 = {0, 0, 0, 0}}}
#else
    .ipv6_addr = {.in6_u = {.u6_addr32 = {0, 0, 0, 0}}}
#endif

其中“ipv6_addr”是 struct in6_addr 类型。我不明白为什么如果 __GNUC> 3,它的成员 in6_u 会更改为“in6_u”。

我的问题是:为什么/何时 GCC 版本会影响 struct in6_addr 中的字段名称?

谢谢。

更新:我的主机系统有 GCC 4.1.2,但 in6_addr 定义为:

in /usr/include/netinet/in.h

/* IPv6 address */
struct in6_addr
  {
    union
      {
        uint8_t u6_addr8[16];
        uint16_t u6_addr16[8];
        uint32_t u6_addr32[4];
      } in6_u;
#define s6_addr                 in6_u.u6_addr8
#define s6_addr16               in6_u.u6_addr16
#define s6_addr32               in6_u.u6_addr32
  };

gcc 版本是:

$/usr/bin/gcc -v
Using built-in specs.
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --disable-plugin --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic --host=x86_64-redhat-linux
Thread model: posix
gcc version 4.1.2 20080704 (Red Hat 4.1.2-50)

最佳答案

这里关注的结构定义,struct in6_addr ,来自 C 运行时库(在 <netinet/in.h> 中)。 C 运行时库通常与所使用的操作系统紧密耦合,但与所使用的 C 编译器不紧密耦合。对于定义 __GNUC__ 的 C 编译器来说尤其如此。为任何值(至少有其中三个:GCC、clang 和 icc);这些编译器被设计为可用于许多不同的操作系统和运行时。因此,原则上,测试__GNUC__不会告诉您有关来自运行时的结构定义的任何有用信息。

我怀疑这个“遗留代码”的作者在两个不同的 Linux 发行版上进行了测试,注意到 __GNUC__ 值之间存在意外相关性。以及 <netinet/in.h> 的内容,并且没有费心去寻找更正确的方法来编译他们的代码。

您应该将整个条件替换为:

.ipv6_addr = IN6ADDR_ANY_INIT;

IN6ADDR_ANY_INIT相关标准 ( POSIX.1-2008 spec for <netinet/in.h> ) 要求可用作 in6_addr 类型变量的初始值设定项,将该变​​量设置为 IPv6 通配符地址,该地址的所有位均为零。所以它会具有相同的效果,而不需要任何 #ifdef根本没有。


为了说明#if __GNUC__ > 3此处应用的测试是错误的,这里有 struct in6_addr 的三个不同定义,所有内容均取自您可能合理地遇到两者的系统 __GNUC_==3__GNUC__==4 (3.x系列现在有点老了,但我仍然时不时地遇到它)。

GNU libc 2.17

struct in6_addr
  {
    union
      {
        uint8_t __u6_addr8[16];
#if defined __USE_MISC || defined __USE_GNU
        uint16_t __u6_addr16[8];
        uint32_t __u6_addr32[4];
#endif
      } __in6_u;
  };

NetBSD 6.1

struct in6_addr {
        union {
                __uint8_t   __u6_addr8[16];
                __uint16_t  __u6_addr16[8];
                uint32_t  __u6_addr32[4];
        } __u6_addr;                    /* 128-bit IP6 address */
};

Windows 7(官方 SDK;反常不提供 netinet/in.h ):

struct in6_addr {
    union {
        UCHAR     Byte[16];
        USHORT    Word[8];
    } u;
};

关于c - GCC 4 中的 in6_addr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18922569/

相关文章:

linux - 如何关闭具有子分区的 luks 容器

linux - Git、单一游戏和跨平台开发

c++ - 本土工作队列与英特尔 TBB

c++ - 是否可以编写这些 pure_assert 和 const_assert 宏?

c - 在 switch 语句中使用枚举类型

linux - Bash:如何计算?

c++ - 检测 WM_MOUSEMOVE 是否由触摸/笔引起

c - 如何在 c 中使用 64 位内联汇编?

c - 为什么 printf with\n 会产生段错误?

c++ - 为什么 gets() 需要更多字符