int 在我的機器上是 4 個位元組,long 8 個位元組,等等。
嘿,所以我在 C 中遇到了一個非常有趣的事情,并開始想知道結構如何管理它們內部的資料。我認為它像陣列一樣作業,但是天哪,我錯了。所以基本上,我認為里面的資料可以自我總結,但我發現堆疊溢位,由于處理器的架構要求,一些編譯器可能會做一些優化。還有對齊。我找到了兩個關于對齊的鏈接,我想計算我的結構的大小,我已經做了一些實驗,但我想我在某些方面理解了這一點,而在某些方面則不然。這就是我想創建該主題的原因,因為我無法完全掌握回答這些主題的人提供的一些示例。例如:
#include <stdio.h>
struct test {
char a;
char b;
int c;
long d;
int e;
};
int main(void){
printf("test = %d\n", sizeof(test));
return 0;
}
輸出:
test = 24
我期待編譯器做這樣的優化:
char a是 1 個位元組,char b是 1 個位元組,因此我們不需要對齊。char b 是 1 個位元組,int c是 4 個位元組,因此我們需要對齊 3 個位元組。int c是4個位元組,long d是8個位元組,因此我們需要對齊4個位元組。long d是8個位元組,int e是4個位元組,因此我們需要對齊4個位元組。直到此時,總大小為 29。用上限四舍五入到最接近的偶數給出 30。那么為什么是 24?
我還發現char a char b給定的填充等于 2 個位元組,所以我們只需要再對齊 2 個位元組,因此也許這就是我犯錯誤的地方。另外,如果我添加更多變數:
#include <stdio.h>
struct test {
char a;
char b;
int c;
long d;
int e;
char f;
char g;
char h;
char i;
};
int main(void){
printf("test = %d\n", sizeof(test));
return 0;
}
輸出:
test = 24
總大小仍然是 24 位元組。但是如果我再添加一個變數:
#include <stdio.h>
struct test {
char a;
char b;
int c;
long d;
int e;
char f;
char g;
char h;
char i;
char j;
};
int main(void){
printf("test = %d\n", sizeof(test));
return 0;
}
輸出:
test = 32
大小更改為總共 32 個位元組。為什么?究竟會發生什么?對不起,如果這個問題的答案對你來說很明顯,但我真的不明白。另外我不知道這是否因編譯器而異,所以如果我沒有提供一些資訊,請告訴我,我會添加它。
uj5u.com熱心網友回復:
這一切都歸結為對齊。編譯器希望讓每個元素與一個地址對齊,該地址是該專案大小的倍數,因為硬體可以通過這種方式最有效地訪問它。(并且在某些架構上,硬體只能以這種方式訪問??它);不允許未對齊的訪問。)
您的結構中有一個元素long int的大小為 8,因此它的對齊將驅動其他所有元素。以下是您的第一個結構的布局方式:
0 1 2 3 4 5 6 7
--- --- --- --- --- --- --- ---
0 | a | b | pad | c |
--- --- --- --- --- --- --- ---
8 | d |
--- --- --- --- --- --- --- ---
16 | e | padding |
--- --- --- --- --- --- --- ---
因此,如您所見,大小為 24,包括兩個不可見的、未命名的“填充”欄位,分別為 2 位元組和 4 位元組。
結構填充和對齊可能會令人困惑。(我花了大量令人尷尬的嘗試才得到正確的答案。)幸運的是,您通常不必擔心任何這些,因為這是編譯器的問題,而不是您的問題。
您可以使用offsetof宏讓編譯器告訴您它是如何布置結構的:
int main(void){
printf("a @ %zd\n", offsetof(struct test, a));
printf("b @ %zd\n", offsetof(struct test, b));
printf("c @ %zd\n", offsetof(struct test, c));
printf("d @ %zd\n", offsetof(struct test, d));
printf("e @ %zd\n", offsetof(struct test, e));
printf("size = %zd\n", sizeof(struct test));
return 0;
}
在我的機器上(它的行為似乎和你的一樣),這會列印:
a @ 0
b @ 1
c @ 4
d @ 8
e @ 16
size = 24
請注意,我使用了%zd而不是%d,因為sizeof并將offsetof他們的答案作為型別size_t而不是int。
當您添加char欄位f, g, h, 和 時i,它們可以放入第二個填充空間,而不會使整體結構變得更大。只有當您添加時j,它才會將內容推送到另一個 8 位元組的塊中:
0 1 2 3 4 5 6 7
--- --- --- --- --- --- --- ---
0 | a | b | pad | c |
--- --- --- --- --- --- --- ---
8 | d |
--- --- --- --- --- --- --- ---
16 | e | f | g | h | i |
--- --- --- --- --- --- --- ---
24 | j | padding |
--- --- --- --- --- --- --- ---
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/363027.html
上一篇:將二維陣列復制到另一個二維陣列
