淺談C語言中的聯合體

聯合體unionhtml

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

     1)聯合體是一個結構;測試

     2)它的全部成員相對於基地址的偏移量都爲0;spa

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

     4)其對齊方式要適合其中全部的成員;htm

下面解釋這四條描述:blog

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

下面舉例說明:get

如聯合體it

union U
{
    char s[9];
    int n;
    double d;
};

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

測試程序:

複製代碼
/*測試聯合體  2011.10.3*/

#include <iostream>
using namespace std;

union U1
{
char s[9];
int n;
double d;
};

union U2
{
char s[5];
int n;
double d;
};

int main(int argc, char *argv[])
{
U1 u1;
U2 u2;
printf("%d\n",sizeof(u1));
printf("%d\n",sizeof(u2));
printf("0x%x\n",&u1);
printf("0x%x\n",&u1.s);
printf("0x%x\n",&u1.n);
printf("0x%x\n",&u1.d);
u1.n=1;
printf("%d\n",u1.s[0]);
printf("%lf\n",u1.d);
unsigned char *p=(unsigned char *)&u1;
printf("%d\n",*p);
printf("%d\n",*(p+1));
printf("%d\n",*(p+2));
printf("%d\n",*(p+3));
printf("%d\n",*(p+4));
printf("%d\n",*(p+5));
printf("%d\n",*(p+6));
printf("%d\n",*(p+7));
return 0;
}
複製代碼


輸出結果爲:

16
8
0x22ff60
0x22ff60
0x22ff60
0x22ff60
1
0.000000
1
0
0
0
48
204
64
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.

至於打印出的d爲0.000000願意以下。因爲已知該段內存前4字節的單元存儲的數據爲00000001 00000000 00000000 00000000,從上面打印結果48,204,64,0能夠知道後面4個字節單元中的數據爲00110000 11001100 01000000 00000000,所以其表示的二進 制浮點數爲

00000000 01000000 11001100 00110000 00000000 00000000 00000000 00000001

對於double型數據,第63位0爲符號位,62-52 00000000100爲階碼,0000 11001100 00110000 00000000 00000000 00000000 00000001爲尾數,根據其值知道尾數值約爲0,而階碼爲4-1023=-1019,所以其表示的浮點數爲1.0*2^(-1019)=0.00000000000......,所以輸出結果爲0.000000。

出處:http://www.cnblogs.com/dolphin0520/archive/2011/10/03/2198493.html

相關文章
相關標籤/搜索