工作经验总结: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 
相关推荐
理论最高的吻1 天前
98. 验证二叉搜索树【 力扣(LeetCode) 】
数据结构·c++·算法·leetcode·职场和发展·二叉树·c
时光の尘1 天前
C语言菜鸟入门·关键字·void的用法
c语言·开发语言·c++·算法·c#·c·关键字
神一样的老师2 天前
C/C++ 优化,strlen 示例
c
万物复苏1014 天前
【汇编】c++游戏开发
开发语言·笔记·游戏·c
石牌桥网管6 天前
用正则表达式检查是IP否为内网地址
java·c++·golang·正则表达式·php·c
Koishi_TvT7 天前
蓝桥杯c++算法学习【3】之思维与贪心(重复字符串、翻硬币、乘积最大、皮亚诺曲线距离【难】:::非常典型的必刷例题!!!)
c++·学习·算法·游戏·贪心算法·蓝桥杯·c
Ustinian_31010 天前
【C++】 C++游戏设计---五子棋小游戏
c
一叶飘零_sweeeet12 天前
Spring Boot 的核心注解
java·spring boot·c
m1chiru14 天前
C++ 游戏开发:打造高效、性能优越的游戏世界
c
charlie11451419116 天前
从0开始的STM32之旅8 串口通信(II)
stm32·单片机·嵌入式硬件·c·串口通信