工作经验总结: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 
相关推荐
C++ 老炮儿的技术栈10 小时前
有符号变量与无符号变量的区别
服务器·开发语言·前端·数据结构·c++·算法·c
haliu14 小时前
【FHE 同态加密】我们如何实现同态加密推理(十六):未完成清单与已知边界(同态加密推理的精度、性能与安全)
人工智能·嵌入式·c·fhe·推理引擎·c11·边缘推理·同态加密推理
haliu2 天前
【FHE 同态加密】我们如何实现同态加密推理(十五):实测账本——一跳 1.8 小时,钱花在哪(同态加密推理性能剖析)
人工智能·嵌入式·c·fhe·推理引擎·c11·边缘推理·同态加密推理
haliu3 天前
【FHE 同态加密】我们如何实现同态加密推理(十四):为什么 `RESULT=PASS` 不是判据(纯 C11 · 零依赖)
人工智能·嵌入式·c·fhe·推理引擎·c11·边缘推理·同态加密推理
haliu4 天前
【FHE】(十三):位级可复现性——4 线程与 8 线程为什么算出不同的结果
人工智能·嵌入式·c·fhe·推理引擎·c11·边缘推理·同态加密推理
haliu5 天前
【FHE】(十二):为什么我们把 OpenMP 换成了自研线程池
人工智能·嵌入式·c·fhe·推理引擎·c11·边缘推理·同态加密推理
haliu5 天前
【FHE】(十):密文里的 attention——没有 max,softmax 怎么办
人工智能·嵌入式·c·fhe·推理引擎·c11·边缘推理·同态加密推理
西西弗Sisyphus13 天前
Qt 实现一个 水波进度球
c++·qt·c
C++ 老炮儿的技术栈14 天前
我们在设计tcp协议时,要传一个字符串过去,报文:头十长度十内容,是否要把‘\0‘也填入,长度是否包含‘\0‘
开发语言·数据结构·c++·mfc·c
anew___14 天前
舵机——让 Arduino 动起来
c++·stm32·单片机·嵌入式硬件·c