關於C語言中聯合體union占用內存的情況


首先聲明本文主要參考海子的 http://www.cnblogs.com/dolphin0520/archive/2011/10/03/2198493.html這篇博文,並對一些地方做了修改,用紅色標出

     

  當多個數據需要共享內存或者多個數據每次只取其一時,可以利用聯合體(union)。在C Programming Language 一書中對於聯合體是這么描述的:

     1)聯合體是一個結構;

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

     3)此結構空間要大到足夠容納最"寬"的成員;

     4)其對齊方式要適合其中所有的成員;

下面解釋這四條描述:

     由於聯合體中的所有成員是共享一段內存的,因此每個成員的存放首地址相對於於聯合體變量的基地址的偏移量為0,即所有成員的首地址都是一樣的。為了使得所有成員能夠共享一段內存,因此該空間必須足夠容納這些成員中最寬的成員。對於這句“對齊方式要適合其中所有的成員”是指其必須符合所有成員的自身對齊方式。

下面舉例說明:

如聯合體

1 union U
2 {
3     char s[9];
4     int n;
5     double d;
6 };

 

 

s占9字節,n占4字節,d占8字節,因此其至少需9字節的空間。然而其實際大小並不是9,用運算符sizeof測試其大小為16.這是因為這里存在字節對齊的問題,9既不能被4整除,也不能被8整除。因此補充字節到16,這樣就符合所有成員的自身對齊了。從這里可以看出聯合體所占的空間不僅取決於最寬成員,還跟所有成員有關系,即其大小必須滿足兩個條件:1)大小足夠容納最寬的成員;2)大小能被其包含的所有基本數據類型的大小所整除。

測試程序:  (測試代碼是我用c重新寫的,原文源代碼里面有些小問題)

 
 1  #include <stdio.h>
 2  2 
 3  3 union U1
 4  4 {
 5  5   char s[ 9 ];
 6  6   int n;
 7  7   double d;
 8  8 };
 9  9 
10 10 union U2
11 11 {
12 12   char s[ 5 ];
13 13   int n;
14 14   double d;
15 15 };
16 16 
17 17 int main( void )
18 18 {
19 19   union U1 u1;     /* 原來的代碼此處有誤 */
20 20   union U2 u2;     /* 原來的代碼此處有誤 */
21 21 
22 22   printf( "%d\n", sizeof( u1 ) );
23 23   printf( "%d\n", sizeof( u2 ) );
24 24 
25 25   printf( "0x%x\n", &u1 );
26 26   printf( "0x%x\n", u1.s );      /* &u1.s也正常工作…… 不是數組名就是地址么……*/
27 27   printf( "0x%x\n", &u1.n );
28 28   printf( "0x%x\n", &u1.d );
29 29 
30 30   /*
31 31   printf( "%d\n", u1.s[ 0 ] );
32 32   printf( "%lf\n", u1.d );
33 33   */
34 34 
35 35   u1.n = 1;
36 36   printf( "%d\n", u1.s[ 0 ] );
37 37   printf( "%lf\n", u1.d );
38 38 
39 39   unsigned char *p = ( unsigned char* )&u1;
40 40   printf( "%d\n", *p );
41 41   printf( "%d\n", *(p+1) );
42 42   printf( "%d\n", *(p+2) );
43 43   printf( "%d\n", *(p+3) );
44 44   printf( "%d\n", *(p+4) );
45 45   printf( "%d\n", *(p+5) );
46 46   printf( "%d\n", *(p+6) );
47 47   printf( "%d\n", *(p+7) );
48 48 
49 49   return 0;
50 50 }

 

 

 

 (編譯環境為ubuntu12.04 gcc 4.6.3)

輸出結果為:

16
8
0x585d400
0x585d400
0x585d400
0x585d400
1
0.000000
1
0
0
0
0
0
0
0



對於sizeof(u1)=16。因為u1中s占9字節,n占4字節,d占8字節,因此至少需要9字節。其包含的基本數據類型為char,int,double分別占1,4,8字節,為了使u1所占空間的大小能被1,4,8整除,則需填充字節以到16,因此sizeof(u1)=16.

對於sizeof(u2)=8。因為u2中s占5字節,n占4字節,d占8字節,因此至少需要8字節。其包含的基本數據類型為char,int,double分別占1,4,8字節,為了使u2所占空間的大小能被1,4,8整除,不需填充字節,因為8本身就能滿足要求。因此sizeof(u2)=8。

從打印出的每個成員的基地址可以看出,聯合體中每個成員的基地址都相同,等於聯合體變量的首地址。

對u1.n=1,將u1的n賦值為1后,則該段內存的前4個字節存儲的數據為00000001 00000000 00000000 00000000

因此取s[0]的數據表示取第一個單元的數據,其整型值為1,所以打印出的結果為1.

 

 


免責聲明!

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



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