C語言之——公用體(聯合體)

一、共用體概述

共用體是一種自定義數據類型,它的定義格式爲:

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

http://bbs.bccn.net/thread-122658-1-1.html

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