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

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值