Включают изменения sizeof in_addr в структуре

Хорошо, у меня есть структура, содержащая элемент struct in_addr. Это должно сделать struct 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

Изменить: форматирование/слова

Ответ 1

Это потому, что у вас есть неудачное имя для члена struct in_addr h_addr.

<netdb.h> в glibc содержит следующее:

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

Запустите gcc -E main.c, чтобы посмотреть, как выглядит ваш код после предварительной обработки, ваша структура addrlist_t по существу становится следующей:

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

Это совсем другое дело, чем вы предполагали.