一琳状、定義:
union維護(hù)足夠的空間來放置多個(gè)數(shù)據(jù)成員中的一種磕瓷,而不是為每一個(gè)數(shù)據(jù)成員配置空間。在union中所有的數(shù)據(jù)成員公用一個(gè)空間念逞,同一時(shí)間只能存儲(chǔ)其中一個(gè)數(shù)據(jù)成員困食,并且所有數(shù)據(jù)成員具有相同的起始地址。例子如下:
union _GLKVector4
{
struct { float x, y, z, w; };
struct { float r, g, b, a; };
struct { float s, t, p, q; };
float v[4];
} __attribute__((aligned(16)));
typedef union _GLKVector4 GLKVector4;
一個(gè)union只分配一個(gè)足夠大的空間來容納最大長(zhǎng)度的數(shù)據(jù)成員翎承,以上例子而言硕盹,最大長(zhǎng)度是struct形態(tài),所以GLKVector4的空間大小就是struct數(shù)據(jù)類型的大小叨咖。
二瘩例、大小端模式對(duì)union類型的影響
大端模式(Big_endian): 字?jǐn)?shù)據(jù)的高字節(jié)存儲(chǔ)在低地址中,而字?jǐn)?shù)據(jù)的低字節(jié)則存放在高地址中芒澜。
大端模式.png
小端模式(Little_endian): 字?jǐn)?shù)據(jù)的高字節(jié)存儲(chǔ)在高地址中仰剿,而字?jǐn)?shù)據(jù)的低字節(jié)則存放在低地址中。
小端模式.png
來看下例子:
union
{
int I;
char a[2];
}*p, u;
p =&u;
p->a[0] = 0x39;
p->a[1] = 0x38;
p.i的值應(yīng)該是多少呢痴晦?
分析問題:根據(jù)a[0],a[1]對(duì)應(yīng)的地址可以看出 ,低字節(jié)存儲(chǔ)在高地址中琳彩,所以得出大端模式
誊酌。
union 型數(shù)據(jù)所占的空間等于其最大的成員所占的空間。
對(duì)union 型的成員的存取都是相對(duì)于該聯(lián)合體基地址的偏移量為0 處開始.
也就是聯(lián)合體的訪問不論對(duì)哪個(gè)變量的存取都是從union 的首地址位置開始露乏。
以此得出結(jié)論:
p.i = 0;
三碧浊、如何用程序去判斷當(dāng)前系統(tǒng)的存儲(chǔ)模式?
請(qǐng)寫一個(gè)C 函數(shù)瘟仿,若處理器是Big_endian 的箱锐,則返回0;若是Little_endian 的劳较,則返回1驹止。
問題分析:
- 先分析一下浩聋,按照上面關(guān)于大小端模式的定義,假設(shè)int 類型變量i 被初始化為1臊恋。
- 變量i 占4 個(gè)字節(jié)衣洁,但只有一個(gè)字節(jié)的值為1,另外三個(gè)字節(jié)的值都為0抖仅。
- 如果取出低地址上的值為0坊夫,毫無疑問,這是大端模式撤卢;
- 如果取出低地址上的值為1环凿,毫無疑問,這是小端模式放吩。
- 既然如此拷邢,我們完全可以利用union 類型數(shù)據(jù)的特點(diǎn):所有成員的起始地址一致。
代碼如下
int checkSystem( )
{
union check
{
int I;
char ch;
} c;
c.i = 1;
return (c.ch ==1);
}
四屎慢、分析下面的代碼
在x64 系統(tǒng)下瞭稼,輸出的值為多少?
#include <stdio.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
int a[5]={1,2,3,4,5};
int *ptr1=(int *)(&a+1);
int *ptr2=(int *)(a+1);
printf("%x,%x\n",ptr1[-1],*ptr2);
}
return 0;
}
- 聲明一個(gè)int類型的數(shù)組腻惠, 大小為5环肘。
-
a
即數(shù)組a中第一個(gè)元素的地址。 -
&a
取得整個(gè)數(shù)組a的地址集灌。注意:a和&a的地址是一致的悔雹。 -
*
求地址存儲(chǔ)的值。 -
(int *)(&a + 1)
相當(dāng)于整個(gè)數(shù)組偏移的一個(gè)數(shù)組的長(zhǎng)度欣喧,即:4(int所占的字節(jié)) * 5(5個(gè)元素) = 20 bytes腌零, 然后賦值給ptr1指針。 -
(int *)(a+1)
相當(dāng)于指向數(shù)組的第一個(gè)元素地址唆阿,然后偏移了4(int所占的字節(jié)數(shù))個(gè)bytes益涧。所以ptr2指向了數(shù)組第二個(gè)元素的地址。即:*ptr2 = 2驯鳖。 -
ptr1[-1]
可以演變?yōu)?code>*(ptr1 - 1)闲询,即:ptr1減去4(int的字節(jié))bytes,然后求此時(shí)地址對(duì)應(yīng)的值浅辙。
附上流程圖: