工作经验总结: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 
相关推荐
绯樱殇雪2 天前
函数题 6-8 简单阶乘计算【PAT】
c·pat考试
伏城之外3 天前
LeetCode - 17 电话号码的字母组合
java·javascript·c++·python·leetcode·c
TT-Kun6 天前
算法 | 基础排序算法:插入排序、选择排序、交换排序、归并排序
算法·排序算法·c
Cyan_RA97 天前
C 408—《数据结构》算法题基础篇—链表(上)
java·数据结构·算法·链表·c·408·计算机考研
Artintel8 天前
[学习笔记]《CSAPP》深入理解计算机系统 - Chapter 6 存储器层次结构
笔记·学习·c·csapp
一丝晨光8 天前
安全API
java·开发语言·c++·安全·编程·c·编程语言
伏城之外10 天前
LeetCode - 15 三数之和
java·javascript·c++·python·leetcode·c
终末圆11 天前
Swiper轮播图框架【前端 24】
前端·javascript·数据结构·c++·python·算法·c
终末圆12 天前
使用C语言实现字符推箱子游戏
c语言·开发语言·数据结构·算法·游戏·排序算法·c
打鱼又晒网19 天前
linux文件——文件系统——学习、理解、应用软硬件链接
linux·服务器·数据库·后端·操作系统·c