結構體struct、聯合體union、枚舉類型enum


1.c語言中的類型

1)內置類型——char,short,int,float,double;

2)用戶自定義類型(UDT)——struct結構體,union聯合體,enum枚舉類型

2.內存對齊

2.1概念

1)內存對齊就是編譯器為程序中的每個“數據單元”安排在適當的位置上

2)對於內存對齊問題,主要存在於struct和union等復合結構在內存中的分布情況

2.2規則

1)對於結構的各個成員,第一個成員位於偏移為0的位置,以后的每個數據成員的偏移量 = min ( #pragma pack(n) 指定的n值, 這個數據成員的字節數 ) 的倍數,#pragma pack(n)可以設置, Windows中默認為8,Linux中默認為4;

2)結構或聯合體本身也要進行對齊,其字節大小=min( #pragram pack(n) ,  長度最長的數據成員 )的倍數

struct MyStruct    //MyStruct的內存分布:*xxx | **** | **        (*代表使用,x代表未使用)
{
    char a;    //偏移量為0
    int b; //偏移量為4
    short c; //偏移量為8
};
//windows下MyStruct的字節大小為:1+4+2=7,變成4的倍數:12

2.3為什么要內存對齊

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

2)性能提升:經過內存對齊之后,CPU的內存訪問速度大大提升,原因:

  • 內存讀取粒度:cpu把內存當成是一塊一塊的,塊的大小可以是2,4,8,16 個字節,因此CPU在讀取內存的時候是一塊一塊進行讀取的,塊的大小稱為(memory granularity)內存讀取粒度
  • 假設CPU要讀取一個4字節大小的數據到寄存器中(假設此CPU內存讀取粒度是4),分兩種情況討論:
  1.  數據從0字節開始:直接將0~3四個字節完全讀取到寄存器,完成,這時候沒有任何影響
  2.  數據從1字節開始:首先先將0~3的4個字節讀到寄存器,並再次讀取4~7字節的數據進寄存器,接着把0、5、6、7的數據剔除,最后合並1,2,3,4字節的數據進寄存器,這些額外操作大大降低了CPU的性能

2.union聯合體

2.1概念

1)聯合體union類似於結構體struct(struct概念:不同類型數據的集合體)

2)聯合體用同一段內存單元存放不同數據類型的成員,在使用時,一次只能使用其中的一個成員

3)它的所有成員相對於基地址的偏移量都為0

4)union的大小取決於它所有的成員中,占用空間最大的一個成員的大小,並且union的大小要能被其他成員的大小所整除

union U1
{
    char s[11];
};

union U2    //s占11字節,n占4字節,d占8字節,所以至少需11字節的空間,但11不能被8整除,所以補充字節到16
{
    int n;
    char s[11];
    double d;
};

int main()
{
    cout << sizeof(U1) << endl;        //輸出:11
    cout << sizeof(U2) << endl;        //輸出:16

    return 0;
}

2.2應用

1)當多個類型的變量要占用同一片內存時,可以使用聯合體:檢測當前機器是采用大端還是小端

2)當多個事物只取其一時(“n選1”),可以使用聯合體:

試題:假設網絡節點A和網絡節點B中的通信協議涉及 四類報文,報文格式為“報文類型字段+報文內容的結構體”,四個報文內容的結構體類型分別為Struct1~ Struct4,請編寫程序以最簡單的方式組織一個統一的報文數據結構。
分析:
報文的格式為“報文類型+報文內容的結構體”,在真實的通信中,每次只能發四類報文中的一種,我們可以將四類報文的結構體組織為一個union(共享一段內存,但每次有效的只是一種),然后和報文類型字段統一組織成一個報文數據結構。
//報文內容聯合體
union PacketContent
{
    Struct1 pkt1;
    Struct2 pkt2;
    Struct3 pkt1;
    Struct4 pkt2;
};

//統一的報文結構
struct Packet
{
    unsigned char pktType;//報文類型
    PacketContent pktContent;//報文內容
};

4.enum枚舉類型

4.1概念

1)枚舉可以讓一些數字符號化

2)c語言中枚舉常量是按照int來處理

3)c語言的枚舉變量可以++,c++的枚舉變量不可以

4.2定義的格式

enum 枚舉類型名 {枚舉常量0=int常量(可無,默認值為0),枚舉常量1=int常量(可無,默認值為1),枚舉常量2,枚舉常量3=int常量(可無,默認值為3),…};
enum Color { red, blue };
enum Color cfq;
cfq = red;
++cfq;    //c語言的枚舉變量可以++
enum Color { red, orange, blue };
Color hehe;
hehe = red;
++hehe;    //錯誤,c++的枚舉變量不可以++

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM