1、結構體記憶體對齊
結構體記憶體對齊在筆試和面試中經常被問到,所以做個總結,首先通過代碼驗證不同結構體的記憶體大小:
#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; }
代碼運行結果為:

通過上述代碼運行結果可以發現Node1和Node2定義了相同個數的變數,但是Node1的大小為12,Node2的大小為8,這是為什么呢?
這里首先明確兩個概念:對齊數和最大對齊數,在結構體中對齊數就是每個成員型別的大小,如Node1中,對齊數為{1,4,1},在陣列中,對齊數不是陣列的大小,而是陣列成員的大小,所以Node3的對齊數為{1,1},Node4的對齊數為{1,4},最大對齊數是對齊數中的最大值(gcc編譯器),最大對齊數可能受編譯器的影響,通常編譯器會有編譯器對齊數,最大對齊數應該是編譯器對齊數和結構體最大對齊數中較小值,如VS編譯器對齊數為8,如果結構體的最大對齊數為16,那么計算結構體的最大對齊數應該為8,我的編譯器為gcc,所以最大對齊數為結構體對齊數中的最大值,
知道最大對齊數后,就可以計算結構體的大小了,需要明確結構體的大小一定是最大對齊數的整數倍,那么Node1和Node2的成員型別是一樣的,為什么Node1的大小為12位元組,Node2的大小為8位元組呢,這是因為結構體記憶體的連續性,在存盤容量沒有到最大對齊數的記憶體大小時,只要能夠保存這個成員,結構體就會將該成員變數保存在一個最大對齊樹的記憶體空間內,這樣就避免了記憶體的過度浪費,所以,上述各結構體的記憶體大小計算方式如下:
sizeof(Node1)= 1 + 3(浪費)+ 4 + 1 + 3(浪費) = 12
sizeof(Node2)= 1 + 1 + 2(浪費)+ 4 = 8
sizeof(Node3) = 1 + 1 * 10 = 11
sizeof(Node4) = 1 + 3(浪費)+ 4 * 10 = 44
那么結構體嵌套結構體的大小應該怎么計算呢?舉以下例子:
#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; }
代碼運行的結果為:

可以明確,嵌套結構體的對齊數為所嵌套結構體的最大對齊數,所以Node1的對齊數為{1,4,1},Node2的對齊數為{1,4,8},最大對齊數分別為4和8,則代碼里兩個結構體的大小計算方式為:
sizeof(Node1)= 1 + 3(浪費)+ 4 + 1 + 3(浪費) = 12
sizeof(Node2)= 1 + 7(浪費)+ 12 + 4(浪費)+ 8 = 24
2、共用體的記憶體大小
對于以下共用體,讀取它大小的代碼如下:
#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; }
代碼運行結果為:

共用體之所以叫共用體,就是因為它的成員變數共享記憶體,既然共享記憶體,那么共用體占用的記憶體空間一定要可以保存記憶體最大的成員型別,而un1的最大記憶體成員為double型,大小為8位元組,所以un1的大小為8位元組,那么un2的記憶體大小為什么不是5呢?這是因為要記憶體對齊,共用體也遵循記憶體對齊原則,un2的最大對齊數是4,因此un2的大小應該是4的整數倍數,所以,sizeof(un2)= 8.
3、列舉的大小
這里順帶提一下列舉的記憶體大小,代碼驗證如下:
#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; }
代碼運行結果為:

可見列舉型別的大小是編譯器根據定義的值自行給定的,實際使用中很少會超出4位元組大小,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/341670.html
標籤:C
