我看到如下代码:(我正在处理的项目中的旧代码)
#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/