问题 包括在struct中更改sizeof in_addr


好的,我有一个包含a的结构 struct in_addr 元件。 这应该是结构 addrlist_t 至少 12字节大小(8 + 4)。平台是 amd64

#include <netinet/in.h> // struct in_addr
#include <stdio.h> // printf()
#include <netdb.h> // toggles size of struct addrlist_t

struct addrlist_t {
    struct addrlist_t *next;
    struct in_addr h_addr;
};

int main(int argc, char *argv[]) {
    printf("%zu + %zu = %zu\n",
        sizeof (struct addrlist_t *), sizeof (struct in_addr), 
        sizeof (struct addrlist_t)
    );
    return 0;
}

这是完全出乎意料的输出:

$cc main.c -o main -Wall -Wwrite-strings -pedantic -std=gnu99 -Wall -Werror
$./main
8 + 4 = 8

这似乎毫无意义。组合尺寸应至少为12,而不是更小!

但现在,何时 #include &lt;netdb.h&gt; 被删除,预期输出出现:

$./main
8 + 4 = 16

同样的事情发生在 -std=gnu99 被替换为 -std=c99

有人可以解释这种行为吗?

为了完整性:

$file main
main: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=709ab89d012d8b5a6ae7423fd80ce643288cba95, not stripped

编辑:格式/单词


12436
2018-01-20 10:32


起源

@Gopi不,因为OP的结果是 小 总和。这看起来很神奇。我在C99模式下在ideone上运行它,打印出来 4 + 4 = 8 (我猜他们有32位环境)。 - unwind
#define _POSIX_C_SOURCE 200809L没有它,我可以在Mac OS X 10.10上使用clang 3.5 x64重新输出你的输出。有了它,它的16,正如预期的那样。 - WhozCraig
你是如此接近自己找到它:) - Ja͢ck


答案:


这是因为你有一个不幸的名字 struct in_addr h_addr 会员。

<netdb.h> 在glibc中包含这个:

# define    h_addr  h_addr_list[0] /* Address, for backward compatibility.*/                       

运行gcc -E main.c以查看预处理后代码的外观, 你的struct addrlist_t基本上变成了这个:

struct addrlist_t {
    struct addrlist_t *next;
    struct in_addr h_addr_list[0];
};

这与你的意图完全不同。


15
2018-01-20 10:45



Ooah ..好抓! :-)我喜欢这种微妙动作的预处理器......; - > - alk
该标题中的周围行可能与我对POSIX特征宏的发现有关, 发布在这里 供参考(其Darwin / clang btw)。 - WhozCraig
谢谢,这个问题让我有些头疼 - mwarning
@mwarming我建议在包含任何标题之前,在文件顶部使用适当的值定义_POSIX_C_SOURCE(和/或_XOPEN_SOURCE) - 这就是它的用途,从技术上讲,你不能保证默认配置不是什么定义。 - Random832