C++結(jié)構(gòu)體字節(jié)對齊和共用體大小
1、結(jié)構(gòu)體內(nèi)存對齊
結(jié)構(gòu)體內(nèi)存對齊在筆試和面試中經(jīng)常被問到,所以做個總結(jié)
通過代碼驗(yàn)證不同結(jié)構(gòu)體的內(nèi)存大小:
#include <stdio.h> struct Node1{ char c1; int val1; char c2; }; struct Node2{ char c1; char c2; int val1; }; struct Node3{ char c1; char array[10]; }; struct Node4{ char val1; int arrar[10]; }; int main(){ printf("Node1 size = %d\n",sizeof(struct Node1)); printf("Node2 size = %d\n",sizeof(struct Node2)); printf("Node3 size = %d\n",sizeof(struct Node3)); printf("Node4 size = %d\n",sizeof(struct Node4)); return 0; }
代碼運(yùn)行結(jié)果為:
通過上述代碼運(yùn)行結(jié)果可以發(fā)現(xiàn)Node1
和Node2
定義了相同個數(shù)的變量,但是Node1的大小為12,Node2的大小為8,這是為什么呢?
這里首先明確兩個概念:對齊數(shù)和最大對齊數(shù),在結(jié)構(gòu)體中對齊數(shù)就是每個成員類型的大小,如Node1中,對齊數(shù)為{1,4,1},在數(shù)組中,對齊數(shù)不是數(shù)組的大小,而是數(shù)組成員的大小,所以Node3的對齊數(shù)為{1,1},Node4的對齊數(shù)為{1,4}。最大對齊數(shù)是對齊數(shù)中的最大值(gcc編譯器),最大對齊數(shù)可能受編譯器的影響,通常編譯器會有編譯器對齊數(shù),最大對齊數(shù)應(yīng)該是編譯器對齊數(shù)和結(jié)構(gòu)體最大對齊數(shù)中較小值,如VS編譯器對齊數(shù)為8,如果結(jié)構(gòu)體的最大對齊數(shù)為16,那么計算結(jié)構(gòu)體的最大對齊數(shù)應(yīng)該為8。我的編譯器為gcc,所以最大對齊數(shù)為結(jié)構(gòu)體對齊數(shù)中的最大值。
知道最大對齊數(shù)后,就可以計算結(jié)構(gòu)體的大小了,需要明確結(jié)構(gòu)體的大小一定是最大對齊數(shù)的整數(shù)倍。那么Node1和Node2的成員類型是一樣的,為什么Node1的大小為12字節(jié),Node2的大小為8字節(jié)呢。這是因?yàn)榻Y(jié)構(gòu)體內(nèi)存的連續(xù)性,在存儲容量沒有到最大對齊數(shù)的內(nèi)存大小時,只要能夠保存這個成員,結(jié)構(gòu)體就會將該成員變量保存在一個最大對齊樹的內(nèi)存空間內(nèi)。這樣就避免了內(nèi)存的過度浪費(fèi)。
所以,上述各結(jié)構(gòu)體的內(nèi)存大小計算方式如下:
- sizeof(Node1)= 1 + 3(浪費(fèi))+ 4 + 1 + 3(浪費(fèi)) = 12
- sizeof(Node2)= 1 + 1 + 2(浪費(fèi))+ 4 = 8
- sizeof(Node3) = 1 + 1 * 10 = 11
- sizeof(Node4) = 1 + 3(浪費(fèi))+ 4 * 10 = 44
那么結(jié)構(gòu)體嵌套結(jié)構(gòu)體的大小應(yīng)該怎么計算呢?舉以下例子:
#include <stdio.h> struct Node1{ char c1; int val1; char c2; }; struct Node2{ char c1; struct Node1 node; double val1; }; int main(){ printf("Node1 size = %d\n",sizeof(struct Node1)); printf("Node2 size = %d\n",sizeof(struct Node2)); return 0; }
代碼運(yùn)行的結(jié)果為:
可以明確,嵌套結(jié)構(gòu)體的對齊數(shù)為所嵌套結(jié)構(gòu)體的最大對齊數(shù),所以Node1的對齊數(shù)為{1,4,1},Node2的對齊數(shù)為{1,4,8},最大對齊數(shù)分別為4和8,則代碼里兩個結(jié)構(gòu)體的大小計算方式為:
- sizeof(Node1)= 1 + 3(浪費(fèi))+ 4 + 1 + 3(浪費(fèi)) = 12
- sizeof(Node2)= 1 + 7(浪費(fèi))+ 12 + 4(浪費(fèi))+ 8 = 24
2、共用體的內(nèi)存大小
對于以下共用體,讀取它大小的代碼如下:
#include <stdio.h> union un1{ int val; char c; double d; }; union un2{ int val; char array[5]; }; int main(){ printf("un1 size = %d\n",sizeof(union un1)); printf("un2 size = %d\n",sizeof(union un2)); return 0; }
代碼運(yùn)行結(jié)果為:
共用體之所以叫共用體,就是因?yàn)樗某蓡T變量共享內(nèi)存,既然共享內(nèi)存,那么共用體占用的內(nèi)存空間一定要可以保存內(nèi)存最大的成員類型,而un1的最大內(nèi)存成員為double型,大小為8字節(jié),所以un1的大小為8字節(jié),那么un2的內(nèi)存大小為什么不是5呢?這是因?yàn)橐獌?nèi)存對齊,共用體也遵循內(nèi)存對齊原則,un2的最大對齊數(shù)是4,因此un2的大小應(yīng)該是4的整數(shù)倍數(shù),所以,sizeof(un2)= 8.
3、枚舉的大小
這里順帶提一下枚舉的內(nèi)存大小,代碼驗(yàn)證如下:
#include <stdio.h> enum Colour { RED, GREEN, BLUE }; enum ProgramLanguage { python = 0xffffffffff, c = 8, java }; int main() { printf("Colour size = %d\n",sizeof(enum Colour)); printf("ProgramLanguage size = %d\n",sizeof(enum ProgramLanguage)); return 0; }
代碼運(yùn)行結(jié)果為:
可見枚舉類型的大小是編譯器根據(jù)定義的值自行給定的,實(shí)際使用中很少會超出4字節(jié)大小。
到此這篇關(guān)于C++結(jié)構(gòu)體字節(jié)對齊和共用體大小的文章就介紹到這了,更多相關(guān)結(jié)構(gòu)體字節(jié)對齊和共用體大小內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言中字符和字符串處理(ANSI字符和Unicode字符)
這篇文章主要介紹了C語言與C++中字符和字符串處理(ANSI字符和Unicode字符)的詳細(xì)內(nèi)容,非常的全面,這里推薦給大家,希望大家能夠喜歡。2015-03-03基于C++實(shí)現(xiàn)酒店管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了基于C++實(shí)現(xiàn)酒店管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-03-03C++實(shí)現(xiàn)LeetCode(37.求解數(shù)獨(dú))
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(37.求解數(shù)獨(dú)),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07C語言數(shù)據(jù)結(jié)構(gòu)系列篇二叉樹的遍歷
本章將會詳細(xì)講解二叉樹遍歷的四種方式,分別為前序遍歷、中序遍歷、后續(xù)遍歷和層序遍歷。在學(xué)習(xí)遍歷之前,會先帶大家回顧一下二叉樹的基本概念2022-02-02C++數(shù)據(jù)封裝以及定義結(jié)構(gòu)的詳細(xì)講解
這篇文章主要詳細(xì)講解了C++數(shù)據(jù)封裝以及定義結(jié)構(gòu),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05