C语言 匿名联合体和匿名结构体

文章一:

定义结构体、联合的时候,有时候需要定义一个匿名的结构,这样访问成员的时候不需要增加一级操作

但是MDK默认不允许使用匿名!!!!

所以我们需要增加一个编译指令:

#pragma anon_unions

实际使用中,我们在其他数据结构中不需要这个功能,所以就得取消之,所以要用到下面两个编译指令:

#pragma push

#pragma pop

有点出入堆栈的感觉,其实push的作用就是保存当前的编译变量,而pop的作用是恢复,整体使用的方式如下:

// Start of section using anonymous unions
#pragma push
#pragma anon_unions
/** 此处定义需要匿名的结构\联合    */
// TODO

// End of section using anonymous unions
#pragma pop

文章二:

匿名联合体和匿名结构体顾名思义,就是没有名字的联合体和结构体,没有名字哪怎么用?拿来用?

在嵌入式数据通信里面,大部分都是使用联合体,将有实际意义的结构体和字节数组互相转换。

typedef struct

{

uint8_t head; //头

uint8_t cmd; //功能字

int16_t x; //传感器x轴数据

int16_t y; //传感器y轴数据

int16_t z; //传感器z轴数据

uint8_t end; //尾

uint8_t checkSum; //校验

}Packet_t;

typedef union

{

uint8_t data[10];

Packet_t packet;

}Datagram_t;

Datagram_t datagram;

如上所示,如果已经通过 datagram.data 接收到数据,想要从数据中提取传感器x轴数据,则只要通过 datagram.packet.x 就可以获取x轴数据。

上面的 Datagram_t 联合体中可以将 Packet_t packet;成员使用匿名结构体替换

typedef struct

{

uint8_t head; //头

uint8_t cmd; //功能字

int16_t x; //传感器x轴数据

int16_t y; //传感器y轴数据

int16_t z; //传感器z轴数据

uint8_t end; //尾

uint8_t checkSum; //校验

}Packet_t;

typedef union

{

uint8_t data[10];

Packet_t; //不给实际名字

}Datagram_t;

Datagram_t datagram;

这时想要从数据中提取传感器x轴数据,则只要通过 datagram.x 就可以获取x轴数据。

但是如果还想要保留 datagram.packet.x 这样的访问方式,怎么办?

#define INHERIT_EX(__TYPE, __NAME) \

union \

{ \

__TYPE; \

__TYPE __NAME; \

};

typedef struct

{

uint8_t head; //头

uint8_t cmd; //功能字

int16_t x; //传感器x轴数据

int16_t y; //传感器y轴数据

int16_t z; //传感器z轴数据

uint8_t end; //尾

uint8_t checkSum; //校验

}Packet_t;

typedef union

{

uint8_t data[10];

INHERIT_EX(Packet_t, packet);

}Datagram_t;

Datagram_t datagram;

可以在联合体 Datagram_t 内部在创建一个匿名联合体

union

{

Packet_t;

Packet_t packet;

};

匿名联合体中再加上一个匿名结构体 Packet_t;

这样 就可以通过 datagram.x 和 datagram.packet.x 这两种方式访问x轴数据。

但是用了匿名联合体和匿名结构体也就是省略了调用packet 成员的步骤。

就省略了一个步骤,也没啥太大作用啊!这里的确是没有发挥太大作用,但是使用C语言开发大型项目,使用面向对象思想开发时,这个就很有用了。尤其是多层继承时,A结构体继承与B结构体、B结构体又继承C结构体… 使用匿名联合体的优势就体现出来了,A可以直接调用结构体B、C…的所有成员。

最后嵌入式开发常见的几个C编译器比如IAR MDK GCC等都是支持的匿名联合体和结构体的,如果不支持可以粘贴下面的代码到自己的系统头文件中,就可以让你的匿名代码在意思几个环境下获得支持。

/* ------------------- Start of section using anonymous unions ------------------ */

#if defined(__CC_ARM)

#pragma push

#pragma anon_unions

#elif defined(__ICCARM__)

#pragma language=extended

#elif defined(__GNUC__)

/* anonymous unions are enabled by default */

#elif defined(__TMS470__)

/* anonymous unions are enabled by default */

#elif defined(__TASKING__)

#pragma warning 586

#else

#warning Not supported compiler type

#endif

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值