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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

C语言结构体内存对齐

發布時間:2023/12/20 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言结构体内存对齐 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

結構體內存對齊

如何計算結構體的大小?

首先得掌握結構體的對齊規則:

1.第一個成員在與結構體變量偏移量為0的地址處。(將第一個成員放在結構體內存的第0處)

2.其他成員變量要對齊到某個數字(對齊數)的整數倍的地址處。(從0地址處開始,偏移量逐漸增減,每個字節加一,第二個成員開始,將成員的字節大小跟對齊數(VS2019編譯器的默認對齊數是 8)進行比較,選兩者中較小的,把該變量放到小的對齊數的偏移量地址上)

對齊數 = 編譯器默認的一個對齊數與該成員大小的較小值。

  • VS中默認的對齊數為8
  • Linux - 沒有默認對齊數的概念

3.結構體總大小為最大對齊數(每個成員變量都有一個對齊數)的整數倍。(如果全部成員自身的的大小已經放入內存,但最后一個成員的尾字節所在的偏移量不是最大對其數的整數倍,則在最后要浪費空間直到剛好到整數倍為止)

4.如果嵌套了結構體的情況,嵌套的結構體對齊到自己的最大對齊數的整數倍處,結構體的整體大小就是所有最大對齊數(含嵌套結構體的對齊數)的整數倍。

struct S { //類型大小 VS默認對齊數 兩者中小的對齊數char c1; // 1 8 1int i; // 4 8 4double d; // 8 8 8 }; int main() {struct S s;printf("%d\n",sizeof(s)); //結構體大小為16,并不是簡單的變量大小相加 }

為什么存在內存對齊?

大部分的參考資料都是這樣說的:

1.平臺原因(移植原因)︰不是所有的硬件平臺都能訪問任意地址上的任意數據的;某些硬件平臺只能在某些地址處取某些特定類型的數據,否則拋出硬件異常。

⒉.性能原因︰數據結構(尤其是棧)應該盡可能地在自然邊界上對齊。原因在于,為了訪問未對齊的內存,處理器需要作兩次內存訪問;而對齊的內存訪問僅需要一次訪問。

總體來說︰

結構體的內存對齊是拿空間來換取時間的做法。


那在設計結構體的時候,我們既要滿足對齊,又要節省空間,如何做到∶

1.讓占用空間小的成員盡量集中在一起。

2.修改默認對齊數

之前我們見過了#pragma這個預處理指令,這里我們再次使用,可以改變我們的默認對齊數。

#pragma pack(2) //設置默認對齊數為2 struct s1 {char c1;int i;char c2; }; #pragma pack() //取消設置的默認對齊數,還原為默認

此時結構體大小為8,如果設置默認對齊數為1的話,則成員緊挨著存放,等于沒有對齊


offsetof宏:

用于計算結構體中某變量相對于首地址的偏移量(以字節為單位)

函數原型:offsetof (type,member)

使用:

#include <stdio.h> #include <stddef.h> //需要引入頭文件 struct s1 {char c1;int i;char c2; }; int main() {printf("%d\n", offsetof(struct s1, c1)); //0,C1在偏移量為0的地址處printf("%d\n", offsetof(struct s1, i)); //4,i在偏移量為4的地址處printf("%d\n", offsetof(struct s1, c2)); //8,C2在偏移量為8的地址處return 0; }

模擬實現offsetof宏:

#include <stdio.h> struct A {char a;int b;char c;double d; }; #define OFFSETOF(struct_name,mem_name) (int)&(((struct_name *)0)->mem_name) int main() {//模擬實現宏offsetofprintf("%d\n", OFFSETOF(struct A, a));printf("%d\n", OFFSETOF(struct A, b));printf("%d\n", OFFSETOF(struct A, c));printf("%d\n", OFFSETOF(struct A, d));return 0; }

解釋:定義宏時,將0強制轉換為結構體類型,只是0不再是個整型,而是個地址,是結構體的首地址,并沒有真正去創建結構體變量,然后通過->找到相應的結構體變量,&取出該變量的地址,減去0地址,再強制類型轉換為int型,就能輸出變量相對于首地址的偏移量,這里沒有減-0,因為沒有意義,如果規定首地址是0x10,那最后強轉為int之前就要減去首地址0x10,才是偏移量

總結

以上是生活随笔為你收集整理的C语言结构体内存对齐的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。