【一天一個C++小知識】007.C++中的struct、enum和union以及內存對齊與大小端問題

1. struct、enum、union三個關鍵字在C中定義比較麻煩,所以一般和typedef一塊出現,而C++中則不用

2. struct和union中可以定義函數,但是:

2.1 struct和class用法完全相同,class有的功能它都用,唯一的區別在於當沒有指定成員的訪問權限時,struct中默認爲public而class默認爲private

2.2 union也支持三種訪問權限的設置,但是:

2.2.1 union不支持繼承
2.2.2 union不能定義虛函數
2.2.3 union和struct一樣,沒有指定訪問權限時默認爲public
2.2.4 union內的變量共享內存,所以不能用靜態、引用類型
2.2.5 union中不是所有類都可以作爲其成員變量,如果一個類(包括其父類)中還有自定義的constructor、copyconstructor、destructor、virtual functional或copy assignment operator(拷貝賦值運算符)任意一個,則不能
2.2.6 union匿名聯合:定義union的時候不定以名字,僅僅通知編譯器它的成員變量公用一個地址,並且變量本身直接引用,不使用“.”或者“->”,匿名聯合體的用處,能想到是類中定義節省空間,此外可能實現自動類型轉換,比如“union{void *p;int n;};int val;p=&val;”那麼此時直接輸出n就是一個地址值,而不用再把p顯示轉爲int類型。匿名聯合體有幾個特點:
  • 2.2.6.1 不能定義static
  • 2.2.6.2 不能定義函數
  • 2.2.6.3 不支持protected和private
  • 2.2.6.4 全局域定義的匿名union只能是static否則必須放在匿名名字空間中。

3. struct 結構體

3.1 初始化:指定初始化A a={val1=2,val2=1;};;構造函數初始化。

3.2 直接訪問:struct A{int val;int c[10];};A com;A.val=2;;間接訪問:struct A *p;p->a;(也可以(*p).a但是不簡潔)

3.3 自引用struct B{int val;struct B b;};不合法,循環下去永遠不知道結構體的大小;struct B{int val;struct B *b;};合法,因爲一個指針所佔字節數是已知的。

3.4 跑題:int val;cout<<&val;可以,但是char cval;cout<<&cval;不行,因爲&cval是一個char*變量,指向一個字符串,字符串需要以終止符\0結尾,但&cval沒有,所以輸出亂碼。正確的方法是:1.printf(“%p”,&a);2.cout<<(void *)&cval;

4.union即所有成員變量共用一個內存首地址,聯合體的賦值涉及一個大小端的問題:

4.1 大端模式:子數據的高字節存儲在低地址,低字節存儲在高地址

4.2 union型數據所佔據的空間等於最大的成員所佔的空間,對union型成員的存取都是相對於該聯合體基地址偏移量爲0開始的,這樣通過union判斷當前系統模式。union A{char ch[4];int I;} a;a.ch[0]=0x40;a.ch[1]=0x03;a.ch[2]=0x02;a.ch[3]=0x11;printf(“%x”,test.i);數組中下標小的地址也低,內存內容依次爲04、03、02、11一共四個字節,而不分類型直接打印十六進制,應該從內存高地址到低地址看,0x11020304,低位04在低地址上。

5.結構體的內存對齊。

5.1 struct A{char ch;int ival;double dval;}a;len1=sizeof(a)執行這一句代碼,len1值爲16而不是1+4+8,這是因爲結構體中元素是按照定義順序一個一個放到內存中的,但並不是緊密排列。從結構體的首地址開始,每一個元素放置到內存中,它都會認爲內存是以它自己的大小來劃分的,因此,元素放置的位置一定會在自己寬度的整數倍上開始。如果用||表示分隔,則十六個長度應該爲|ch(char)佔一個|NULL|NULL|NULL|ival(int)佔四個|dval(double)佔八個|。

5.2 strcut B{char ch;double dval;int ival;}b;len2=sizeof(b)執行這一代碼,按照上述規則,len2理應爲8+8+4=20,但實際輸出24。這是因爲,在經過上面的規則分析之後,檢查計算出的存儲單元是否爲所有元素中最寬的元素的長度的整數倍,是的話結束,否則補齊它的整數倍。

5.3 這樣,我們在定義結構體時候,內部的元素應該按所佔字節數從大到小排列,並且考慮補位的影響。

6. enum

6.1 默認以int類型存儲,佔四個字節,可以存儲的最大值0xffffff。但是我們可以通過繼承的方式改變枚舉的大小。C++中規定0<=sizeof(enum)<=sizeof(int),編譯器究竟是分配多少內存,emmmmm~

6.2 另外,enum Test{a=1,b,c=5,d,e}test;test=e;cout<<test;輸出結果爲7,因爲enum會默認給後面未幅值的再最近一個幅值的基礎上加1。

歡迎掃描二維碼關注微信公衆號 深度學習與數學   [每天獲取免費的大數據、AI等相關的學習資源、經典和最新的深度學習相關的論文研讀,算法和其他互聯網技能的學習,概率論、線性代數等高等數學知識的回顧]
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章