工作经验总结: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 
相关推荐
学习前端的小z2 天前
【C++】小乐乐求和问题的高效求解与算法对比分析
c
集大周杰伦4 天前
C语言指针与数组深入剖析及优化示例 指针解读 数组与指针的关系
c语言·c
学习前端的小z4 天前
【C++ 】for 循环系统深入解析与实现法比较
c
无为扫地僧5 天前
五、windows上vscode构建c/c++环境
c++·vscode·c
学习前端的小z5 天前
【C++】小乐乐求和题目分析n变量类型讨论
c
学习前端的小z6 天前
【C++】青蛙跳跃问题解析与解法
c
枫の准大一7 天前
【C++游记】Vector的使用和模拟实现
c
学习前端的小z9 天前
【C++】数的性质问题分析与优化
c
talentestors14 天前
Codeforces Round 992 (Div. 2) 解题报告
c++·c·题解·cpp
物联网牛七七16 天前
24、宏定义和条件编译
条件编译·宏定义·c语言学习笔记