C語言中的結構體填充和打包



什麼是C語言中的結構體填充?

C語言中的結構體填充是由CPU架構處理的過程。結構體填充在結構體中新增一定數量的空位元組,以便資料成員在記憶體中自然對齊。對齊要求由處理器架構決定,而不是由語言本身決定。當然,對齊要求會根據某個CPU架構的資料匯流排大小或其他架構方面的考慮而改變。

透過示例理解結構體填充

讓我們定義如下結構體型別:

struct struct1 {
   char x;
   int y;
   char z;
};

示例1

讓我們檢查這種型別變數所需的位元組大小:

#include <stdio.h>

struct struct1{
   char a;
   char b;
   int c;
};

int main(){

   printf("Size: %d", sizeof(struct struct1));  
   return 0;
}

輸出

執行此程式碼時,將產生以下輸出:

Size: 8

結果與預期相反。

考慮到char型別需要1個位元組,int型別需要4個位元組,人們可能會認為輸出應該是“1 + 1 + 4 = 6位元組”。

Structure Padding

但是,CPU架構需要更改此結構。考慮到我們使用的是具有32位處理器的CPU,它一次讀取4個位元組,這意味著一個字等於4個位元組。

在一個CPU週期中,它訪問char "a",然後是char "b"和int "c"的前兩個位元組。在第二個週期中,訪問其他兩個位元組。

即使我們只想讀取“c”,也需要兩個CPU週期。為此,CPU在儲存“c”值的位元組之前新增兩個空位元組。這種機制稱為填充

Structure Padding

現在解釋了我們上面獲得的結果,即結構體型別的尺寸為8位元組。

示例2

讓我們更改上述結構體成員的順序,並設定“b”和“c”的型別。

#include <stdio.h>

struct struct1{
   char a;
   int b;
   char c;
};

int main(){

   printf("size: %d", sizeof(struct struct1));
   return 0;
}

輸出

執行程式碼並檢查其輸出:

size: 12

在第一個字的4個位元組中,第一個位元組分配給char "a",後面跟著三個空位元組。

構成下一個字的接下來的4個位元組用於儲存int "b"。隨後,在接下來的4個位元組組中,只有一個用於“c”。但是,結構體大小為12。

什麼是C語言中的結構體打包?

另一方面,結構體打包是一種最小化填充影響的機制,從而嘗試減少浪費的記憶體空間。我們可以使用某些pragma指令和屬性來實現打包。

透過示例理解結構體打包

由CPU架構強制執行的填充是不可避免的,但是有一些方法可以最大限度地減少填充。可以使用以下方法:

  • 使用 #pragma pack(1) 指令
  • 使用 packed 屬性

使用 #pragma pack(1) 指令

#pragma pack(1) 預處理器指令強制編譯器忽略填充,並在記憶體分配過程中將結構體成員端對端對齊。

示例

讓我們將此指令新增到前面使用的程式碼頂部,並檢視結果:

#include <stdio.h>
#pragma pack(1)

struct struct1{
   char a;
   int b;
   char c;
};

int main(){

   printf("size: %d", sizeof(struct struct1));
   return 0;
}
輸出

執行程式碼並檢查其輸出:

size: 6

我們可以看到結構體填充已被避免,並減少了記憶體浪費。

使用 __attribute__((packed))

使用GCC,我們可以使用屬性來指定結構體和聯合體型別的各種特殊屬性。這些屬性是:aligned, deprecated, packed, transparent_union, unusedvisibility。應用這些屬性的語法是“__attribute__ ((...))”。

示例

在這裡,我們將使用packed屬性在我們的結構體型別定義中。

#include <stdio.h>

struct __attribute__((packed)) struct1{
   char a;
   int b;
   char c;
};

int main(){

   printf("size: %d", sizeof(struct struct1));
   return 0;
}
輸出

執行程式碼並檢查其輸出:

size: 6

此方法也避免了填充的影響。

廣告
© . All rights reserved.