c++ unio 學習總計

c++的 union類型平時用的真心少 從來沒有認真研究過他

今天看了幾道c++的筆試題   有幾道 關於union的 題目  現在總結下

第一題:

union V {
struct X {
unsigned char s1:2;
unsigned char s2:3;
unsigned char s3:3;
} x;
unsigned char c;
} v;
v.c = 100;
printf("%d", v.x.s3);


答案爲 3  (s2 爲 1   ,  s1爲0)

網上的解釋

v是聯合體(共用體)變量,共有兩個元素x和c,都需要一個字節,它們分配於同一個地址。

而x是結構體變量,共有三個元素s1、s2、s3,分別佔2位、3位、3位。分配內存時低位在前,最位在後。

當有v.c=100(其二進制爲01100100)時,各變量的關係及內存存儲情況見圖所示。
其中x的成員s3爲二進制的011,即十進制的3,所以輸出結果爲3。


同理的第二題:

#i nclude <stdio.h>
union
{
int i;
char x[2];
}a;
void main()
{
a.x[0] = 10;
a.x[1] = 1;
printf("%d",a.i);
}
int 爲 .. ...  0000 0001  0000 0010  

答案:266 (低位低地址,高位高地址,內存佔用情況是Ox010A)


學習中 看了些文章 有所收穫 下面轉兩篇文章 


一篇是 union和struct的 大小問題

1,對於union,對齊的大小是最大的基本元素的對齊大小;對象的大小必須是該基本元素大小的整數倍;
2,對於struct,對齊的大小也是最大的基本元素的對齊大小,對象的大小需要考慮元素的對齊,並且需要是最大基本元素的整數倍;同時有#pragma pack修飾的情況,關於struct請詳細參考另外一個帖子。
3,這裏所說的struct和union的對齊,是指其作爲其他複雜對象中的元素的時候要求的對齊,對於本身大小的計算並沒有關係。本身的大小隻和其所包含的基本元素的對齊有關係。

(copy 一段網上的對齊規則 1,數據成員對齊規則:結構的數據成員,第一個數據成員放在offset爲0的地方,以後每個數據成員存儲的起始位置要從該成員大小的整數倍開始(比如int在32位機爲4字節,則要從4的整數倍地址開始存儲) 2,,結構體作爲成員:如果一個結構體裏有某些結構體成員,則結構體成員要從其內部最大元素大小的整數倍地址開始存儲(struct a裏存有 stuct b, b裏有char,int,double等元素,那麼b應該從8的整數倍開始存儲) 3,收尾工作:結構體的總大小,也就是sizeof的結果,必須是其內部最大成員的整數倍,不足的要補齊。)
例子一:
union U1
{
 char a[9]; //對齊大小是1,大小是9個字節
 int b; //對齊大小是4,大小是4個字節
};
所以該union的對齊大小是4個字節;大小爲大於等於max(9,4)=9併爲4的整數倍,所以是12字節。


例子二:
union U1_Another
{
 char a[9]; //對齊大小是1,大小是9個字節
 double b; //對齊大小是8,大小是8個字節
};
所以該union的對齊大小是8個字節,大小是大於等於9併爲8的整數倍,即爲16字節;


例子三:
union U2
{
 U1 a; //對齊大小是4個字節,大小是12字節
 double b; //對齊大小是8個字節,大小是8字節
};
所以該union的對齊大小是8個字節,大小是16;


例子四:
struct S1
{
 char a[13]; //對齊大小是1字節,位置是[0,12]
 double c; //對齊大小是8字節,位置是[16,23]
}
所以該結構體是8字節對齊,大小爲24個字節;


另一篇是 union和大小端模式 :

一.union數據類型

union顧名思義,聯合體,float,int,char等等類型數據共用一塊內存空間。其大小爲佔據內存空間最大的那個變量的空間大小。

eg:

union

{

 float a;

 char b[2];

}u_test;

那麼union所佔的內存空間大小爲float類型變量a所佔的內存大小,在常見32位計算機上爲4字節。

 

二.大小端對union的影響

一般x86體系的計算機採用的是小端模式:高高低低,高字節數據存放在內存中的高地址處,低字節數據存放在內存中的低地址處。

反之,大端模式就是高低高低了,高字節數據存放在內存中的低地址處,低字節數據存放在內存中的高地址處。

 

16bit寬的數0x1234Little-endian模式(以及Big-endian模式)CPU內存中的存放方式(假設從地址0x4000開始存放)爲:

 

內存地址

小端模式存放內容

大端模式存放內容

0x4000

0x34

0x12

0x4001

0x12

0x34

說明:內存中最小的單位爲1字節(8bit),上表中的0x4000正是這樣一個字節內存,顯然相對於0x4001而言,0x4000是低地址。低字節數據0x34就存放於內存的低地址0x4000處,而高字節數據0x12就存放於內存的高地址0x4001處。

 

32bit寬的數0x12345678Little-endian模式以及Big-endian模式)CPU內存中的存放方式(假設從地址0x4000開始存放)爲:

內存地址

小端模式存放內容

大端模式存放內容

0x4000

0x78

0x12

0x4001

0x56

0x34

0x4002

0x34

0x56

0x4003

0x12

0x78

 

三.測試大小端對union的影響,假設union分配的內存地址首地址爲0,

eg:

union u_test

{

  int a;

  char b[2];

}mm;

寫一個測試函數:

void test_union(void)

{

       mm.a = 65*256 + 97;   

       printf("union's b[0] is: %c,b[1] is: %c\n",mm.b[0],mm.b[1]);

}

這個結構體的大小爲int a的大小4字節。假設在內存中是從地址0開始的連續4個單位。顯然這4個字節的內存塊的存放着a的值。則按照高高低低的原則,低內存地址0應該存放的是低字節數據97,依此往下存放,即內存地址爲1的內存單元存放着十進制數爲65的數據,內存地址爲2的內存單元存放着0,內存地址爲3的內存單元存放着0

內存地址

小端模式存放內容

0

存放着十進制97

1

存放着十進制65

2

0

3

0

所以上面的函數test_union執行的結果將會是打印小寫字母a(97)和大寫字母A(65).

那如果是大端模式將會是怎樣的結果呢?如下:

內存地址

大端模式存放內容

0

0

1

0

2

十進制65

3

十進制97

 

.測試CPU是大端還是小端模式?

當然對於一般的CPU,我們已經瞭解到:

Big Endian : PowerPCIBMSun

Little Endian : x86DEC

ARM既可以工作在大端模式,也可以工作在小端模式。

如果不知平臺到底運行於何種模式,也根據上面的這些特性可以自己測試出來?

  1. /*
  2. ** 函數名:checkCPU
  3. ** 輸 入:none
  4. ** 輸 出:0-- 大端模式
  5. ** 1-- 小端模式
  6. ** 功 能:檢測CPU的大小端模式
  7. */
  8. int checkCPU(void)
  9. {
  10.   union check
  11.   {
  12.     int i;
  13.     char j;
  14.   }c;

  15.   c.= 1;

  16.   return (c.== 1);
  17. }

注: union 爲低地址對齊 如果是 little 則int 爲  01 00 00 00 然後 j 對齊低地址 爲01 所以c.j==1

       如果爲big爲 00 00 00 01  然後j對齊低地址 爲 00 所以c.j==0

或者:

bool IsBigendian()
{
    unsigned short usData = 0x1122;
    unsigned char *pucData = (unsigned char*)&usData;
    return (*pucData == 0x11);
}
注: 轉換 也是從地地址開始處理 若爲 little usData 存爲 22 11  pucData從低地址開始獲取 則爲 22

                                                        若爲 big  usData存爲 11 22 pucData從低地址開始獲取 則爲 11


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