【原创】C语言面向对象,this call C语言实现class C语言 匿名联合体和匿名结构体
#include <stdio.h> #include <stdlib.h> typedef struct user_t { int t; char *userName; void (*setUserName)(char* name,int); void (*print)(); }UserT; /*重点在这里*/ #define THIS_CALL \ int ex;\ {_asm mov ecx, ebp}\ {_asm sub eax, ecx}\ {_asm sub eax, 4h}\ {_asm mov ecx, eax}\ {_asm mov eax, ebp}\ {_asm go_sub :}\ {_asm add eax, 4}\ {_asm sub ecx, 4h}\ {_asm jg go_sub}\ {_asm mov ecx, esp}\ {_asm mov esp, eax}\ {_asm pop eax}\ {_asm mov ex, eax}\ {_asm mov esp, ecx} #define FUNC(Type,f,arg) f##arg {\ THIS_CALL \ Type this;\ this = (Type)ex;\ //GO语言定义方式 #define func(Type,f,arg,rt) rt f##arg {\ THIS_CALL \ Type this;\ this = (Type)ex;\ func (UserT*, setUserNamae, (char *name, int a),void) this->userName = name; this->userName = name; } func (UserT*, print, (), void) printf("%s\n", this->userName); } #define CALL_S(e)\ size_t addr = e; \ {_asm mov eax, esp}\ {_asm push addr} #define $$(e) {CALL_S(e);} (0,\ e)\ void initUser(struct user_t* u) { u->setUserName = setUserNamae; u->print = print; } int main() { struct user_t User;initUser(&User); $$(&User)->setUserName("张飞", 2); $$(&User)->print(); while (1){} }
匿名联合体和匿名结构体顾名思义,就是没有名字的联合体和结构体,没有名字哪怎么用?拿来用?
在嵌入式数据通信里面,大部分都是使用联合体,将有实际意义的结构体和字节数组互相转换。
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
java新手自学群 626070845
java/springboot/hadoop/JVM 群 4915800
Hadoop/mongodb(搭建/开发/运维)Q群481975850
GOLang Q1群:6848027
GOLang Q2群:450509103
GOLang Q3群:436173132
GOLang Q4群:141984758
GOLang Q5群:215535604
C/C++/QT群 1414577
单片机嵌入式/电子电路入门群群 306312845
MUD/LIB/交流群 391486684
Electron/koa/Nodejs/express 214737701
大前端群vue/js/ts 165150391
操作系统研发群:15375777
汇编/辅助/破解新手群:755783453
大数据 elasticsearch 群 481975850
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。