2011-08-27 34 views
7

Khi tôi in kích thước của một liên minh như thế này:Tại sao kích thước của công đoàn tôi lớn hơn tôi mong đợi?

union u { 
    char c[5]; 
    int i; 
} un; 

sử dụng này:

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    printf("size of union = %d ",sizeof(un)); 
    return 0; 
} 

tôi nhận được một câu trả lời của 8 sử dụng Visual C++, nhưng tôi mong đợi 5. Tại sao?

Vâng, đối với các ví dụ tương tự, tôi đã làm một cái gì đó như thế này:

int i1 = 0x98761234; 
un.i = i1; 
printf("\n un.c[0] = %x ",un.c[0]); 
printf("\n un.c[1] = %x ",un.c[1]); 
printf("\n un.c[2]= %x ",un.c[2]); 
printf("\n un.c[3] = %x ",un.c[3]); 
printf("\n un.c[4] = %x ",un.c[4]); 
printf("size of union = %d ",sizeof(un)); 

tôi đã nhận kết quả như

un.c[0] = 34; 
un.c[1] = 12; 
un.c[2] = 76; 
un.c[3] = ffffff98; 

tại sao có 6fs tại un.c [3]

Trả lời

11

Toán tử sizeof tạo kích thước của một biến hoặc loại, bao gồm bất kỳ phần đệm cần thiết để phân tách các phần tử trong một mảng thuộc loại đó sao cho mọi thứ vẫn được căn chỉnh chính xác. Vì công đoàn của bạn có thành viên int, nên cần phải căn chỉnh 4 byte, do đó kích thước "tự nhiên" của nó được làm tròn lên tới bội số tiếp theo là 4 byte.


ffffff98 là vì bạn đang biên soạn với chữ ký char. Sử dụng %x với một đối số không phải là unsigned int gây ra hành vi không xác định; những gì bạn nhìn thấy đôi khi được gọi là tiện ích mở rộng đăng nhập. Kết quả của việc đánh răng của bạn là 0x98 được diễn giải lại thành char, là -104. Đây vẫn giữ được giá trị của nó trên được thăng int (điều này được gọi là chương trình khuyến mãi lập luận mặc định), và int -104 khi aliased như unsigned int trở thành 0xffffff98.

1

Trình biên dịch có thể thêm đệm bất cứ nơi nào nó muốn cấu trúc, các đoàn thể và các lớp để tăng tốc độ truy cập bộ nhớ. Bạn đang thấy ảnh hưởng của điều đó. Đối với Visual C++, padding thường là bội số của kích thước của loại thành viên lớn nhất. Trong trường hợp này, thành viên lớn nhất là một int, do đó nó đánh bại công đoàn với 3 byte không sử dụng để làm tổng kích thước 8.

+0

Giả sử số nguyên 4 byte, thành viên lớn nhất là c, đó là 5 byte. Trình biên dịch làm tròn lên đến 8 bằng cách thêm phần đệm. Nếu hệ thống đang sử dụng các số nguyên 8 byte, thì 8 được sử dụng cho kích thước công đoàn. –

+0

@Brian Tôi đã thay đổi câu trả lời của mình ngay trước khi bạn nhận xét là "loại thành viên lớn nhất", để chỉ ra rõ ràng hơn một int. –

+1

Tôi không biết, tôi vẫn không nghĩ câu trả lời của bạn rõ ràng hay chính xác. Bạn nói thành viên lớn nhất là một int, nhưng nó không phải là. Nó là một mảng gồm 5 ký tự. Vì 5> 4 nó làm tròn tới bội số tiếp theo của kích thước từ gốc, làm cho nó trở thành 8. –

3

Căn chỉnh của công đoàn phải là sự liên kết lớn nhất của bất kỳ thành viên nào. Đây là 4. Do đó, kích thước của công đoàn phải được căn chỉnh với kích thước đó. Nó có thể là 5 (như c là thành viên lớn nhất của công đoàn), nhưng vì sự liên kết của toàn bộ công đoàn là 4, kích thước của công đoàn được độn thành 8.

Lưu ý rằng điều này chỉ dành cho VC++. Tiêu chuẩn này không yêu cầu cụ thể. Mặc dù nó cho phép triển khai thực hiện các kiểu pad khi cần thiết, mà VC++ làm. GCC có thể làm điều gì đó khác biệt, và có thể có các công tắc biên dịch thời gian bạn có thể sử dụng để thay đổi hành vi này.

0

Cảm ơn đề xuất của bạn. Tôi đã thử điều này với rất nhiều ví dụ và trông rằng kích thước công đoàn tương đương với (kích thước của phần tử tối đa) + đệm (tùy thuộc vào kích thước của kiểu dữ liệu cao nhất được sử dụng).

2

enter image description here biên dịch thêm vài byte cho sự liên kết

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