日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

sizeof()计算结构体的大小

發(fā)布時間:2023/11/30 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 sizeof()计算结构体的大小 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

原文鏈接:sizeof()計算結(jié)構(gòu)體的大小_海月汐辰-CSDN博客_結(jié)構(gòu)體的sizeof怎么計算

簡要說明:結(jié)構(gòu)體成員按照定義時的順序依次存儲在連續(xù)的內(nèi)存空間,但是結(jié)構(gòu)體的大小并不是簡單的把所有成員大小相加,而是遵循一定的規(guī)則,需要考慮到系統(tǒng)在存儲結(jié)構(gòu)體變量時的地址對齊問題。

一、沒有成員的結(jié)構(gòu)體占用的空間是多少個字節(jié)?

? ? ?答案是:1個字節(jié)。

? ? ?這就是實例化的原因(空類同樣可以被實例化),每個實例在內(nèi)存中都有一個獨一無二的地址,為了達到這個目的,編譯器往往會給一個空類或空結(jié)構(gòu)體(C++中結(jié)構(gòu)體也可看為類)隱含的加一個字節(jié),這樣空類或空結(jié)構(gòu)體在實例化后在內(nèi)存得到了獨一無二的地址,所以空類所占的內(nèi)存大小是1個字節(jié)。

二、首先介紹一個相關(guān)的概念——偏移量

? ? ? ? ? struct stru?
? ? ? ? ?{ ?
? ? ? ? ? ? ? ? ? ? int a; ?//start address is 0
? ? ? ? ? ? ? ? ? ?char b; ?//start address is 4
? ? ? ? ? ? ? ? ? ?int c; ?//start address is 8
? ? ? ? ?};

? ? ? ? ?偏移量指的是結(jié)構(gòu)體變量中成員的地址和結(jié)構(gòu)體變量地址的差。結(jié)構(gòu)體大小等于最后一個成員的偏移量加上最后一個成員的大小。顯然,結(jié)構(gòu)體變量中第一個成員的地址就是結(jié)構(gòu)體變量的首地址。比如上面的結(jié)構(gòu)體,第一個成員a的偏移量為0。第二個成員b的偏移量是第一個成員的偏移量加上第一個成員的大小(0+4),其值為4;第三個成員c的偏移量是第二個成員的偏移量應該是加上第二個成員的大小(4+1)。


三、在實際中,存儲變量時地址要求對齊,編譯器在編譯程序時會遵循兩條原則:

? ? ? ? ? ? ?(1)結(jié)構(gòu)體變量中成員的偏移量必須是成員大小的整數(shù)倍(0被認為是任何數(shù)的整數(shù)倍)?

? ? ?(2)結(jié)構(gòu)體大小必須是所有成員大小的整數(shù)倍,也即所有成員大小的公倍數(shù)。

例子1:
struct stru1 ?
{ ?
? ? ?int a; ?//start address is 0
? ? ?char b; ?//start address is 4
? ? ?int c; ?//start address is 8
};

PS:用sizeof求該結(jié)構(gòu)體的大小,發(fā)現(xiàn)值為12。int占4個字節(jié),char占1個字節(jié),結(jié)果應該是9個字節(jié)才對啊,為什么呢?這個例子中前兩個成員的偏移量都滿足要求,但第三個成員的偏移量為5,并不是自身(int)大小的整數(shù)倍。編譯器在處理時會在第二個成員后面補上3個空字節(jié),使得第三個成員的偏移量變成8。結(jié)構(gòu)體大小等于最后一個成員的偏移量加上其大小,上面的例子中計算出來的大小為12,滿足要求。

例子2:

struct stru2 ?
{ ?
? ? ? int i; ?//start address is 0
? ? ? short m; ?//start address is 4
};

PS:成員i的偏移量為0;成員m的偏移量為4,都不需要調(diào)整。但計算出來的大小為6,顯然不是成員m大小的整數(shù)倍。因此,編譯器會在成員m后面補上2個字節(jié),使得結(jié)構(gòu)體的大小變成8從而滿足第二個要求。

例子3、4:

?struct stru3 ?
{ ??
? ? ? ?char i; ?//start address is 0?
? ? ? ?int m; ? //start address is 4
? ? ? ?char n; ?//start address is 8
}; ?
struct stru4 ?
{ ?
? ? ? ?char i; ?//start address is 0
? ? ? ?char n; ?//start address is 1
? ? ? ?int m; ?//start address is 4
?};?

雖然結(jié)構(gòu)體stru3和stru4中成員都一樣,但sizeof(struct stru3)的值為12而sizeof(struct stru4)的值為8。

由此可見,結(jié)構(gòu)體類型需要考慮到字節(jié)對齊的情況,不同的順序會影響結(jié)構(gòu)體的大小。

四、 對于嵌套的結(jié)構(gòu)體,需要將其展開。對結(jié)構(gòu)體求sizeof時,上述兩種原則變?yōu)?#xff1a;
? ? ? ?(1)展開后的結(jié)構(gòu)體的第一個成員的偏移量應當是被展開的結(jié)構(gòu)體中最大的成員的整數(shù)倍。

? ? ? ?(2)結(jié)構(gòu)體大小必須是所有成員大小的整數(shù)倍,這里所有成員計算的是展開后的成員,而不是將嵌套的結(jié)構(gòu)體當做一個整體。

例子1:

struct stru5 ?
{ ?
? ? ? short i; ?
? ? ? struct ??
? ? ? { ?
? ? ? ? ? ?char c; ?
? ? ? ? ? ?int j; ?
? ? ? } tt; ??
? ? ? int k; ?
};

結(jié)構(gòu)體stru5的成員tt.c的偏移量應該是4,而不是2。整個結(jié)構(gòu)體大小應該是16。

例子2:

struct stru6 ?
{ ?
? ? ? char i; ?
? ? ? struct ??
? ? ? { ?
? ? ? ? ? ?char c; ?
? ? ? ? ? ?int j; ?
? ? ? } tt; ??
? ? ? char a; ?
? ? ? char b; ?
? ? ? char d; ?
? ? ? char e; ?
? ? ? int f; ?
};

結(jié)構(gòu)體tt單獨計算占用空間為8,而stru6的sizeof則是20,不是8的整數(shù)倍,這說明在計算sizeof(stru6)時,將嵌套的結(jié)構(gòu)體ss展開了,這樣stu6中最大的成員為tt.j,占用4個字節(jié),20為4的整數(shù)倍。如果將tt當做一個整體,結(jié)果應該是24了。

五:另一個特殊的例子是結(jié)構(gòu)體中包含數(shù)組,其sizeof應當和處理嵌套結(jié)構(gòu)體一樣,將其展開,如下例子:

struct array ?
{ ?
? ? float f; ?
? ? char p; ?
? ? int ?arr[3]; ?
};

其值為20。float占4個字節(jié),到char p時偏移量為4,p占一個字節(jié),到int arr[3]時偏移量為5,擴展為int的整數(shù)倍,而非int arr[3]的整數(shù)倍,這樣偏移量變?yōu)?,而不是12。結(jié)果是8+12=20,是最大成員float或int的大小的整數(shù)倍。

測試環(huán)境:vc++6.0

測試代碼:
?

//#ifndef __cplusplus//#endif#include <iostream> #include "stdio.h" #include <stdlib.h> using namespace std;struct stru_empty {}; struct stru1 { int a; //start address is 0char b; //start address is 4int c; //start address is 8 }; struct stru2 { int i; //start address is 0short m; //start address is 4 }; struct stru3 { char i; //start address is 0 int m; //start address is 4char n; //start address is 8 }; struct stru4 { char i; //start address is 0char n; //start address is 1int m; //start address is 4};struct stru5 { short i; struct { char c; int j; } ss; int k; }; struct stru6 { char i; struct { char c; int j; } tt; char a; char b; char d; char e; int f; }; struct stru7 { char i; struct { char c; //int j; } tt; char a; char b; char d; char e; int f; }; struct array { float f; char p; int arr[3]; }; int main() { struct stru6 st6;struct stru7 st7;struct array ar;printf("sizof(char)=%d \n",sizeof(char));printf("sizof(int)=%d \n",sizeof(int));printf("sizof(short int)=%d \n",sizeof(short int));printf("sizof(long int)=%d \n",sizeof(long int));printf("sizof(long)=%d \n",sizeof(long));printf("sizof(float)=%d \n\n",sizeof(float));printf("sizof(stru_empty)=%d \n",sizeof(stru_empty));printf("sizof(stru1)=%d \n\n",sizeof(stru1));printf("sizof(stru2)=%d \n\n",sizeof(stru2));printf("sizof(stru3)=%d \n\n",sizeof(stru3));printf("sizof(stru4)=%d \n\n",sizeof(stru4));printf("sizof(stru5)=%d \n\n",sizeof(stru5));printf("sizof(stru6)=%d \n",sizeof(stru6)); printf("sizof(stru6.tt)=%d \n",sizeof(st6.tt));printf("the address of stru6.i=%d \n",&st6.i);printf("the address of stru6.a=%d \n\n",&st6.a);printf("sizof(stru7)=%d \n",sizeof(stru7));printf("sizof(stru7)=%d \n",sizeof(st7.tt));printf("the address of stru7.i=%d \n",&st7.i);printf("the address of stru7.a=%d \n\n",&st7.a);printf("sizof(ar)=%d \n",sizeof(ar));printf("sizof(ar.f)=%d \n",sizeof(ar.f));printf("sizof(ar.arr)=%d \n",sizeof(ar.arr));return 0; }

運行結(jié)果:

?

總結(jié)

以上是生活随笔為你收集整理的sizeof()计算结构体的大小的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。