一、共用體概述
共用體是一種自定義數據類型,它的定義格式爲:
union 共用體名
{
成員列表
};
結構體和共用體的區別在於:
- 結構體的各個成員會佔用不同的內存,互相之間沒有影響;
- 共用體的所有成員共享同一段內存,同一時間只能儲存其中一個數據成員,共用體所佔的空間不僅取決於最寬成員,還跟所有成員有關係,即其大小必須滿足兩個條件:1)大小足夠容納最寬的成員;2)大小能被其包含的所有基本數據類型的大小所整除。
- 所有的數據成員具有相同的起始地址(即固定首地址)。
一段測試代碼如下:
#include<stdio.h>
union U1
{
char s[9];
int n;
double d;
float f;
};
union U2
{
char s[9];
int n;
float f;
};
int main(void)
{
printf("%d\r\n",sizeof(double));//8
printf("%d\r\n",sizeof(float));//4
printf("%d\r\n",sizeof(int));//4
printf("%d\r\n",sizeof(union U1));//16
printf("%d\r\n",sizeof(union U2));//12
return 0;
}
二、共用體妙用
對同一個內存單元進行多種不同規則解析
union U1
{
char s[4];
float f;
};
三、共用體使用陷阱
對比如下兩段代碼:
typedef union
{
uint32_t word;
uint8_t bytes[4];
}word_msg_t;
unit32_t read_mesg(void)
{
word_rnsg_t tmp;
/*注:tmn bvte[O]對府幹tmp.word的高8位,tmp byter[l]對應於tmp.WOfO的次高8位,依次類*/
tmp.bytes[O]=read_byte();
tmp.bytes[1]=read_byte();
tmp.bytes[2]=read_byte();
tmp.bytes[3]=read_byte();
retern(trap.word);
}
以上代碼格式在各種通信協議中使用的頻率很高,接收端接收到的數據一般都以字節爲單位存放,主控程序需要根據相應的協議將接收到的多個字節進行組合。爲了實現相同的功能,《MISRA-C:2004》推薦了read_msg()函數的另外一種寫法。
uint32_trcad_msg(void)
{
uint32_t word;
Word=((unit32_t)read_byte())<<24;
word=word│(((unit32_t)read_byte())<<16);
word=word│(((unit32_t)read_byted_byte<<8);
word=word│(((unit32_t)read_byte());
return(word):
}
無論從程序的清晰程度還是執行效率來講,程序段1都優於程序段2。然而,程序段1在不同的平臺上運行結果是不同的(涉及到大小端的問題)假設read_byte()函數返回的數據依次是0x01、0x02、0x03和0x04,則在Intel體系中,程序段1中read_msg()函數的返回值是0x432l;在Motorola體系中,read_msg()的返回值是0x1234。
但無論在Intel體系還是Motorola體系中,程序2中read_msg()的返回值都是0x1 234。
以上是聯合體中多字節整型字節排放順序不定導致漏洞的一個例子。
REF:
https://blog.csdn.net/weixin_34409822/article/details/86037807