工作经验总结:C语言中类函数的宏定义、宏定义拼接、常量指针与指针常量的识别记忆技巧整理

一、类函数的宏定义

初步接触AUTOSARS架构代码时,发现其中用了很多类函数的宏定义以及宏定义拼接等一些技巧来进行模块化,如果对C语言掌握不够熟练则可能会觉得比较难看懂,下面简单介绍一下几种见到的类函数宏定义使用方式。

大致的类函数的宏定义如下:

cpp 复制代码
// memclass type
#define AUTOMATIC
#define USERMAITC

// ptrclass type
#define SOC_CODE
#define HVIL_CODE

// Function like  macro
/* memclass is not used */
#define VAR(type, memclass)         type
#define CONST(type, memclass)       const type
#define FUNC(rettype, memclass)     rettype

/* ptrclass is not used */
#define P2FUNC(rettype, ptrclass, fctname)             rettype (* fctname)
#define CONSTP2FUNC(rettype, ptrclass, fctname)        rettype (* const fctname)

/* memclass and ptrclass is not used */
#define FUNC_P2CONST(rettype, ptrclass, memclass)      const rettype *
#define FUNC_P2VAR(rettype, ptrclass, memclass)        rettype *
#define P2VAR(ptrtype, memclass, ptrclass)             ptrtype *
#define P2CONST(ptrtype, memclass, ptrclass)           const ptrtype *          //常量指针: 地址可改,内容不可改
#define CONSTP2VAR(ptrtype, memclass, ptrclass)        ptrtype * const          //指针常量: 地址不可改,内容可改
#define CONSTP2CONST(ptrtype, memclass, ptrclass)      const ptrtype * const 

简单概述下类函数的宏定义,其实相当于把我们正常变量和函数声明给宏定义化,并且在宏定义中加上额外的标识来指明是内存是自动分配,以及变量或者函数归属于哪个模块。

例子1 变量的定义:

用一个变量的定义来举例:

cpp 复制代码
#define AUTOMATIC
#define USERMAITC

#define VAR(type, memclass)         type

其中:

cpp 复制代码
VAR(int, AUTOMATIC) value;

等效:

cpp 复制代码
int value;

通过宏定义的方式我们可以通过自定义的标识,来了解该变量类型内存分配方式 。并且假如不同APP层的变量的类型别名不同,我们可以直接搜索全局VAR关键字,来修改适配对应APP的不同类型别名(而不是通过搜索类型或者变量名来一个个对应修改)

例子2 函数的定义:

用一个函数的声明来举例:

cpp 复制代码
// memclass type
#define AUTOMATIC
#define USERMAITC

// ptrclass type
#define SOC_CODE
#define HVIL_CODE

/* memclass is not used */
#define FUNC(rettype, memclass)     rettype

其中:

cpp 复制代码
FUNC(void, SOC_CODE) APP_SOC_TASK(void);

等效于:

cpp 复制代码
void APP_SOC_TASK(void);

通过宏定义的方式我们可以通过自定义的标识,来了解该函数返回类型归属模块

例子3 较复杂的模块化定义:

cpp 复制代码
#define RTE_E_OK (0x00)

// memclass type
#define AUTOMATIC
#define USERMAITC

// ptrclass type
#define SOC_CODE
#define HVIL_CODE
#define RTE_CODE

/* ptrclass is not used */
#define FUNC(rettype, memclass)     rettype

/* memclass and ptrclass is not used */
#define P2VAR(ptrtype, memclass, ptrclass)             ptrtype *


FUNC(void , CDD_CODE) RTE_Get_Fault_int_TO (P2VAR(int, AUTOMATIC, RTE_APPL_DATA) Returned_Value)
{
    /* do something */
}

#define RTE_Get_Fault_int( Returned_Value )  ( RTE_Get_Fault_int_TO( Returned_Value ), ((VAR(int, AUTOMATIC)) RTE_E_OK))

其中:

cpp 复制代码
int result = 0;
int test_flag = 0;

result = RTE_Get_Fault_int(&test_flag);

等效于:

cpp 复制代码
// Step 1
FUNC(void , CDD_CODE) RTE_Get_Fault_int_TO (P2VAR(int, AUTOMATIC, RTE_APPL_DATA) Returned_Value)
// 等效于
void RTE_Get_Fault_int_TO ( int *Returned_Value )


// Step 2
#define RTE_Get_Fault_int( Returned_Value )  ( RTE_Get_Fault_int_TO( Returned_Value ), ((VAR(int, AUTOMATIC)) RTE_E_OK))
result = RTE_Get_Fault_int(&test_flag);
// 等效于
result = ( RTE_Get_Fault_int_TO(&test_flag), ( (int) 0u ) )

通过这种方式来把不同功能的接口进行模块化整合

例子4 较复杂的类型定义:

cpp 复制代码
// memclass type
#define AUTOMATIC
#define USERMAITC

// ptrclass type
#define SOC_CODE
#define CDD_CODE    
#define HVIL_CODE

/* memclass is not used */
#define CONST(type, memclass)       const type

/* memclass and ptrclass is not used */
#define P2CONST(ptrtype, memclass, ptrclass)           const ptrtype *          //常量指针: 地址可改,内容不可改

typedef struct
{
    int a;
    int b;
}Rte_APP_SOC;

其中:

cpp 复制代码
typedef P2CONST(struct Rte_APP_SOC, AUTOMATIC, RTE_CONST)   Rte_SelfType_APP_SOC;

CONST(struct Rte_APP_SOC, RTE_CONST) Rte_Inst_APP_SOC = {0};
CONST(Rte_SelfType_APP_SOC, RTE_CONST)  Rte_Self_APP_SOC = &Rte_Inst_APP_SOC;

等效于:

cpp 复制代码
// Step1
typedef P2CONST(struct Rte_APP_SOC, AUTOMATIC, RTE_CONST)   Rte_SelfType_APP_SOC;
// 等效于
typedef const struct Rte_APP_SOC *  Rte_SelfType_APP_SOC;

// Step2
CONST(struct Rte_APP_SOC, RTE_CONST) Rte_Inst_APP_SOC = {0};
// 等效于
const struct Rte_APP_SOC Rte_Inst_APP_SOC  = {0};

// Step3
CONST(Rte_SelfType_APP_SOC, RTE_CONST)  Rte_Self_APP_SOC = &Rte_Inst_APP_SOC;
// 等效于
const Rte_SelfType_APP_SOC Rte_Self_APP_SOC = &Rte_Inst_APP_SOC;
// 等效于
const struct Rte_APP_SOC * Rte_Self_APP_SOC = &Rte_Inst_APP_SOC;

二、宏定义的拼接用法

宏定义拼接的用法也是有助于功能的模块化。

例如:接收到不同零部件的CAN信号后, 对不同零部件的CAN信号进行解析

例子1 零部件模块化CAN信号解析:

cpp 复制代码
#define Com_GetValue(ELEMENTTYPE, PROP, ByteValue)      Com_GetValue_##ELEMENTTYPE##PROP(ByteValue)
#define Com_GetValue_RXSIG_FILTRALG(ByteValue)          ((uint8)(ByteValue) >> 1)

其中:

cpp 复制代码
uint8 sig = 1;
uint8 value = 0;

value = Com_GetValue(RXSIG, _FILTRALG, sig);

等效于:

cpp 复制代码
// Step1
value = Com_GetValue_RXSIG_FILTRALG(sig);
// 等效于
value = ((uint8)(sig) >> 1);

三、C语言中常量指针与指针常量的识别与记忆小技巧

1.常量指针

我们可以通过文字的排序来记住常量指针与指针常量的对应格式

如:常量指针先是常量然后是指针 ;即先是const ,然后才是指针

既然是常量的指针 ,那么指向的地址可以改变 ,指向的是对象为常量 ,则内容不可以改变

所以常量指针地址可改,内容不可改

cpp 复制代码
const int *p

2.指针常量

如:指针常量先是指针然后是常量;即先为指针,然后才是const

既然是指针的常量 ,那么指向的地址不可改 ,但是内容可以修改

所以指针常量地址不可改,内容可改

cpp 复制代码
int * const p 
相关推荐
charlie1145141911 天前
从0开始的STM32之旅8 串口通信(II)
stm32·单片机·嵌入式硬件·c·串口通信
孤寂大仙v1 天前
【C++】AVL树
开发语言·数据结构·c++·c
charlie1145141913 天前
嵌入式Linux入门具备:C语言基础与基本驱动学习(2):Linux GIibc IO基础
c语言·学习·c·io·嵌入式软件
charlie1145141915 天前
从0开始的STM32之旅 7 串口通信(I)
stm32·单片机·嵌入式硬件·c
Java Fans6 天前
C++ 实现俄罗斯方块游戏
c
我要学脑机6 天前
电路知识的回顾
c·电路
Ljw...6 天前
C++游戏开发
c++·c·游戏开发
bin91539 天前
【热门主题】000013 C++游戏开发全攻略
c++·c
charlie1145141919 天前
STM32 从0开始系统学习2
stm32·嵌入式硬件·c·1024程序员节·arm架构·寄存器映射
shylyly_10 天前
string类的模拟实现
开发语言·数据结构·c++·c·string类的模拟实现·手搓