2015-01-20 18 views
11

Ok, tôi có một cấu trúc có chứa một phần tử struct in_addr. Điều này sẽ tạo cấu trúc addrlist_t ít nhất 12 Kích thước byte (8 + 4). Nền tảng là amd64.bao gồm các thay đổi sizeof in_addr trong struct

#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; 
} 

Đây là sản phẩm hoàn toàn bất ngờ:

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

Điều này dường như không có ý nghĩa. Kích thước kết hợp phải tối thiểu là 12, không nhỏ hơn!

Nhưng bây giờ, khi #include &lt;netdb.h&gt; được lấy ra, sản lượng dự kiến ​​sẽ xuất hiện:

$./main 
8 + 4 = 16 

Những điều tương tự xảy ra khi -std=gnu99 được thay thế bằng -std=c99.

Ai đó có thể giải thích hành vi này?

Đối với đầy đủ:

$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 

Edit: định dạng/từ

+1

@Gopi Không, vì kết quả của OP nhỏ hơn * so với tổng. Nó có vẻ rất huyền diệu. Tôi chạy nó trên ideone trong chế độ C99, in '4 + 4 = 8' (tôi đoán họ có môi trường 32-bit). – unwind

+1

'#define _POSIX_C_SOURCE 200809L', mà không có nó tôi có thể repro đầu ra của bạn với clang 3.5 x64 trên Mac OS X 10.10. Với nó, 16 của nó, như mong đợi. – WhozCraig

+0

Bạn đã rất gần với việc tìm kiếm nó cho mình :) –

Trả lời

15

này là bởi vì bạn có một cái tên không may cho struct in_addr h_addr thành viên.

<netdb.h> trong glibc chứa này:

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

Run gcc -E main.c để xem cách mã của bạn chăm sóc preprossessing, addrlist_t struct của bạn về cơ bản trở thành này:

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

Đó là một điều rất khác với những gì bạn dự định.

+0

Ooah .. đẹp bắt! :-) Tôi yêu các bộ xử lý trước cho hành động mềm dẻo như vậy ...; -> – alk

+1

Các dòng xung quanh trong tiêu đề đó cũng có thể jive với những phát hiện của tôi về macro tính năng POSIX, [được đăng tại đây] (http://pastebin.com/ uPt9hY5U) để tham khảo (Darwin/clang btw) của nó. – WhozCraig

+0

Cảm ơn, vấn đề này đã cho tôi một số đầu trầy xước nghiêm trọng – mwarning

Các vấn đề liên quan