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),分兩種情況討論:
- 數據從0字節開始:直接將0~3四個字節完全讀取到寄存器,完成,這時候沒有任何影響
- 數據從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”),可以使用聯合體:
//報文內容聯合體 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++的枚舉變量不可以++