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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

仔细讨论 C/C++ 字节对齐问题⭐⭐

發布時間:2025/3/8 c/c++ 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 仔细讨论 C/C++ 字节对齐问题⭐⭐ 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文:https://www.cnblogs.com/AlexMiller/p/5509609.html

字節對齊的原因

????為了提高 CPU 的存儲速度,編譯器會對 struct 和 union的存儲進行優化,即進行字節對齊

對齊方式

????對于 struct 或 union 中的 struct 或者 union 來說,它們的字節對齊標準就是它的所有成員中字節數最大的數據的字節數。

一般情況下 C/C++ 的變量所占用的字節數

??????? char:??? 1字節;

?? ???? short:?? 2字節;

?? ???? int:?????? 4字節;

?? ???? long:??? 4字節;

?? ???? long long: 8字節;

?? ???? float:??? 4字節;

?? ???? double: 8字節;

?? ???? bool:??? 1字節;

*struct 中字節對齊需要滿足的條件:對齊兩原則

????1、某個變量存放的起始位置相對于結構的起始位置的偏移量該變量字節數的整數倍

????2、結構所占用的總字節數是結構種字節數最長的變量的字節數的整數倍

????例:

1 struct Struct 2 { 3 double d1; 4 char d2; 5 int d3; 6 }a;

  sizeof(a) = 8 + 1 + 3 + 4 = 16。其中補上的 3 個字節是為了讓 int 型數據的起始位置相對于結構起始位置的偏移量為 4 的整數倍

1 struct Struct 2 { 3 char d1; 4 double d2; 5 int d3; 6 }b;

  sizeof(b) = 1 + 7 + 8 + 4 = 20。 20 / 8 = 2 …… 4,所以需要再補上 4 個字節,使之成為 8 的 整數倍

*union 中字節對齊需要滿足的兩個條件:對齊兩原則

????1、unoin 的大小必須足夠容納最寬的成員

????2、union 的大小需要能夠被其所包含的基礎成員類型的大小所整除。

?

字節對齊的另一種方式

????VC提供了 #pragma pack(n) 用來自定義字節對齊方式

????有一下兩種情況:

????????1、n 大于變量的字節數:偏移量只滿足默認的字節對齊方式;

????????2、n 小于變量所占的字節數:偏移量是 n 的整數倍,不使用默認的字節對齊方式。

????例:

1 #pragma pack(push) // 保持對齊狀態2 #pragma pack(4) // 設定為 4 字節對齊3 struct test4 {5 char m1;6  double m2;7   int m3;8 }a;9 #pragma pack(pop) // 恢復對齊狀態 10 sizeof(a) = 1 + 3 + 8 + 4 = 16  // 其中補上三位是因為 n 小于 8,所以 m2 的起始位置相對于結構起始位置的偏移量是 n,即為 4. 11 12 13 #pragma pack(8) 14 struct S1 15 { 16   char a; 17   long b; 18 }; 19 struct S2 20 { 21   char c; 22   struct S1 d; 23   long long e; 24 }; 25 #pragma pack() 26 27 sizeof(S1) = 1 + 3 + 4 = 8 28 sizeof(S2) = 1 + 3 + 8 + 4 + 8 = 24// 其中加上的 4 是因為變量 e 的字節數是 8 ,其相對與起始位置的偏移量必須是 8 的倍數。???

?

字節對齊問題的討論到上邊已經結束了。下面再加上我碰到的兩道題目作為實例:

1、典 ???

1 #include <stdio.h>2 union3 {4 char x[5];5 int i;6 }a;7 8 int main()9 { 10 a.x[0] = 10; 11 a.x[1] = 1; 12 printf("%d\n", a.i); 13 printf("%d\n", sizeof(a)); 14 return 0; 15 }

?

輸出為 266 8

解析:

對 union 分配內存涉及字節對齊問題,在上方已有詳細描述,在此只簡單解釋一番。union 分配的內存必須是 union 中所有基本數據類型的倍數
在此題中即為 1 和 4 的倍數,又 char x[5] 占用 5 個字節,故 union 分配的內存大小應為 8 個字節。
windows 系統中高字節在后,低字節在前。而 char x[5] 只有前兩個元素有值,即兩個值只占 2 個字節,也即 union 中的 int 型數據中只有低兩位上有值。
即 i 的二進制表示為:
????00000000 00000000 00000001 00001010
????即: 2^1 + 2^3 + 2^8 = 266
也相當于十六進制 0x010A, 即: 10 * 16^0 + 1 * 16^2 = 266

題2

struct T { char a; int *d; int b; int c:16; double e; }; T *p; 在64位系統以及64位編譯器下,以下描述正確的是

正確答案: C ??你的答案: C?(正確)

A:sizeof(p) == 24 (8) B:sizeof(*p) == 24  (32) C:sizeof(p->a) == 1   D:sizeof(p->e) == 4  (8)

a占一個字節(注:地址為[0]),d作為64位指針占8個字節(注1:32位占四個字節,p也一樣)(注2:根據上面的準則2,d的偏移量要為8的整數倍,所以d的地址為[8]-[15],而非[1]-[8],下同),b占了4個字節(注:地址為[16][19]),c指定為16為,占了兩個字節(注:地址為[20,21]),e占8個字節,(同d的分析一樣,e的地址應該為[24][31]),所以A的答案應該是8,B的答案是32,C正確,D的答案為8。

這里補充一下進制轉換問題,也是我一并搜集來的:

進制互相轉換

十進制0123456789101112131415
十六進制0123456789ABCDEF
二進制0000000100100011010001010110011110001001101010111100110111101111

  十六進制數字轉換十進制數字: ?? ??? ?

    0x2AF5轉換十進制:?? ??? ??? ?

      5 * 16^0 = 5?? ??? ??? ?

      F * 16^1 = 240?? ??? ??? ?

      A * 16^2 = 2560?? ??? ??? ?

      2 * 16^3 = 8192?? ??? ??? ?

      ---------------?? ??? ??? ?

      5 + 240 + 2560 + 8192 = 10997?? ?

  十進制數字轉換十六進制數字:?? ??? ?

    2500轉換十六進制:?? ??? ??? ?

      2500 / 16 = 156 …… 4?? ??? ??? ?

      156 / 16 = 9 …… 12(C)?? ??? ??? ?

      9 / 16 = 0 …… 9?? ??? ??? ?

      ----------------------?? ??? ??? ?

      得到4C9,倒轉9C4,即2500的十六進制表示是: 0x9C4?? ?

  二進制數字轉換十六進制數字:?? ??? ?

    101110011011.1001?? ??? ?

    采取四合一法,即以二進制的小數點為分界點,向左(或向右)每四位取一位。?? ??? ?

    組分好以后,對照二進制與十六進制數的對應表,將四位二進制按權相加,得到的數就是一位十六進制數,然后按順序排列,小數點的位置不變。?? ??? ?

    結果為:B9B.9?? ??? ?

    需要注意的是,在向左(或向右)取四位時,取到最高位(最低位)如果無法湊足四位,就可以在小數點的最左邊(或最右邊)補0,進行換算。?? ?

  十六進制數字轉換二進制數字:  

    對照二進制與十六進制數的對應表,將十六進制數分為二進制數字,用四位二進制數字按權相加,最后得到二進制數字,小數點依舊。

?

2、

1 #include <iostream>2 using namespace std;3 4 typedef struct A5 {6 char aChar;7 int aInt_2;8 short aInt;9 }TypeA; 10 11 typedef struct B 12 { 13 char bChar[3]; 14 TypeA bA; 15 double bDouble; 16 }TypeB; 17 18 int main() 19 { 20 TypeA a; 21 TypeB b; 22 cout << sizeof(a) << endl << sizeof(b) << endl; 23 return 0; 24 }

輸出為 12 24

解析:

由上述對字節對齊問題的討論很容易便可以得出此題的答案。
sizeof(TypeA) = 1 + 3 + 4 + 2 = 10。 10 / 4 = 2 …… 2,故需要再補上 2 個字節,即 sizeof(TypeA) = 12;
sizeof(TypeB) = 3 + 1 + 12 + 8 = 24。之所以補上 1 個字節是因為 TypeA 類型在 struct TypeB 中的默認對齊方式
是 4 個字節(即 int 的字節大小,也即 struct TypeA 中最長的字節)。

總結

以上是生活随笔為你收集整理的仔细讨论 C/C++ 字节对齐问题⭐⭐的全部內容,希望文章能夠幫你解決所遇到的問題。

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