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

一、类函数的宏定义

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

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

// 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 变量的定义:       

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

#define AUTOMATIC
#define USERMAITC#define VAR(type, memclass)         type

其中: 

VAR(int, AUTOMATIC) value;

 等效:

int value;

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

 例子2 函数的定义:

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

// memclass type
#define AUTOMATIC
#define USERMAITC// ptrclass type
#define SOC_CODE
#define HVIL_CODE/* memclass is not used */
#define FUNC(rettype, memclass)     rettype

其中:

FUNC(void, SOC_CODE) APP_SOC_TASK(void);

等效于:

void APP_SOC_TASK(void);

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

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

#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))

 其中:

int result = 0;
int test_flag = 0;result = RTE_Get_Fault_int(&test_flag);

等效于:

// 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 较复杂的类型定义:

// 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;

其中:

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;

 等效于:

// 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信号解析:

#define Com_GetValue(ELEMENTTYPE, PROP, ByteValue)      Com_GetValue_##ELEMENTTYPE##PROP(ByteValue)
#define Com_GetValue_RXSIG_FILTRALG(ByteValue)          ((uint8)(ByteValue) >> 1)

其中:

uint8 sig = 1;
uint8 value = 0;value = Com_GetValue(RXSIG, _FILTRALG, sig);

等效于:

// Step1
value = Com_GetValue_RXSIG_FILTRALG(sig);
// 等效于
value = ((uint8)(sig) >> 1);

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

1.常量指针

我们可以通过文字的排序来记住常量指针与指针常量的对应格式
如:常量指针先是常量然后是指针;即先是const,然后才是指针
既然是常量的指针,那么指向的地址可以改变,指向的是对象为常量,则内容不可以改变
所以常量指针地址可改,内容不可改

const int *p

2.指针常量

 如:指针常量先是指针然后是常量;即先为指针,然后才是const
既然是指针的常量,那么指向的地址不可改,但是内容可以修改
所以指针常量地址不可改,内容可改

int * const p 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/842409.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入解读 ChatGPT 的基本原理(个人总结版)

引言 背景 人工智能(AI)技术自20世纪中期诞生以来,经历了多次革新和进步。从最早的图灵测试,到20世纪末的深蓝计算机击败国际象棋冠军,再到21世纪初谷歌AlphaGo击败围棋冠军,AI技术的飞速发展改变了人们的…

BEVFormer论文详细解读

文章目录 1. 前言1.1 3D VS 4D1.2 .特征融合过程中可能遇到的问题1.3 .BEV提出背景1.4 .BEV最终得到了什么1.5 .输入数据格式 2. 背景/Motivation2.1 为什么视觉感知要用BEV?2.2 生成BEV视角的方法有哪些?为何选用Transformer呢? 3. Method/S…

DSP教程

/// TMS320F28335 具有 150MIPS、FPU、512KB 闪存、EMIF、12 位 ADC 的 C2000™ 32 位 MCU /// 此文档中的《8.3 内存映射》部分做个大概的了解,用的时候查阅即可。 TMS320F2833x、TMS320F2823x 实时微控制器 数据表 (Rev. Q)PDF /// 这个实验要实际操作&…

分布式锁与ZooKeeper的探索之旅

一、引言 在现代的软件开发中,分布式系统扮演着越来越重要的角色。随着系统的扩展和复杂度的增加,确保多个进程或服务之间的数据一致性变得尤为重要。在这样的背景下,分布式锁的概念应运而生,它为分布式系统提供了一种协调机制&a…

Vapor Mode:Vue.js 的速度与激情,代码界的闪电侠

大家好,我是宝哥。 在快速发展的网络开发世界中,创新的Vue.js团队给我们带来了Vapor Mode。这个新模式优化了Vue的核心渲染过程,帮助我们的应用程序像轻烟一样运行,开发者无需深入复杂的优化工作。 在这篇文章中,我们将…

硝基酪氨酸检测试剂盒Nitrotyrosine ELISA Kit,比色法

硝基酪氨酸是反应体内氧化应激的标记物质。StressMarq可以提供硝基络氨酸的检测试剂盒。酪氨酸硝基化会导致细胞功能损伤。因此检测样本中的硝基酪氨酸含量尤为重要。StressMarq的硝基络氨酸检测试剂盒有多篇文献引用,产品质量有保障。除了有硝基络氨酸的检测试剂盒…

【微积分】Grant Sanderson

梯度:将各个偏导打包 定义:direction of steepest ascent 梯度向量的长度:最速上升方向的陡峭程度 方向导数:偏导的一种拓展 【托马斯微积分学习日记】13.1-线积分_哔哩哔哩_bilibili 概述 16.1line integrals of scalar funct…

直播预告:TinyVue 组件库实战解析,提升组件库构建技能!

在复杂的编码世界里,大家总希望能够寻找更高效、更简洁的解决方案来优化工作流程,提升开发效率。在5月28日晚7点 OpenTiny B站直播间,OpenTiny 非常荣幸地为大家带来一场关于 TinyVue 组件库实战分享的直播。届时,TinyVue 组件库成…

openEuler系统通过shell脚本安装openGauss 5.0.0企业版

上次提到的开机自启动的配置,获得了LD的称赞,然而LD的要求,都是“既得陇复望蜀”的,他又期望我们能实现openGauss安装的“自动化”,于是尝试了下用shell脚本部署,附件中的脚本实测有效,openEule…

JDBC的 PreparedStatement 的用法和解释

文章目录 前言1、封装数据库连接和关闭操作数据库配置文件 config.properties 2、批量添加操作3、查询操作4、修改和删除操作总结 前言 PreparedStatement是预编译的,对于批量处理可以大大提高效率. 也叫JDBC存储过程 1、封装数据库连接和关闭操作 package org.springblade.m…

Leetcode 力扣90. 子集 II (抖音号:708231408)

给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的 子集 (幂集)。 解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。 示例 1: 输入:nums [1,2,2…

线程安全-3 JMM

一.谈一下JMM 1.JMM,JavaMemoryModel,Java内存模型。定义了多线程对共享内存读写操作的行为规范,通过规范多线程对共享内存的读写操作,以保证指令执行和结果的正确性。 2.JMM把内存分为两块 (1)主内存&a…

图论(二)-图的建立

引言: 建图,将图放进内存的方法 常用的建图方式:邻接矩阵,邻接链表,链式前向星 一、邻接矩阵 通过一个二维数组即可将图建立,邻接矩阵,考虑节点集合 ,用一个二维数组定义邻接矩…

迭代器模式(行为型)

目录 一、前言 二、迭代器模式 三、总结 一、前言 迭代器模式(Iterator Pattern)是一种行为型设计模式,提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。总的来说就是分离了集合对象的遍历行为,抽象出…

gcc -m32 一堆报错:No such file or directory

问题:终端执行命令gcc -m32 *.c -o xxx.so 出现一堆缺失文件的报错。 解决办法:库没装全,终端执行下面的命令。 sudo apt install gcc-multilib

sql去除表中某个字段的空格

比如表中名字字段,名字之间有空格,需要把空格去除,应该如何写SQL语句实现? 在SQL中,可以使用TRIM函数来去除字符串两端的空格,如果需要去除字段中的所有空格,可以使用REPLACE函数结合TRIM函数。…

【设计模式】JAVA Design Patterns——Command(事务模式)

🔍目的 将请求封装为对象,从而使你可以将具有不同请求的客户端参数化,队列或记录请求,并且支持可撤销操作。 🔍解释 真实世界例子 有一个巫师在地精上施放咒语。咒语在地精上一一执行。第一个咒语使地精缩小&#xff0…

LabVIEW步开发进电机的串口控制程序

LabVIEW步开发进电机的串口控制程序 为了提高电机控制的精确度和自动化程度,开发一种基于LabVIEW的实时、自动化电机串口控制程序。利用LabVIEW软件的图形化编程特性,通过串口实时控制电机的运行参数,实现电机性能的精准控制与评估。 系统组…

Borel-Cantelli 引理

翻译自大佬 https://huarui1998.com/Notes/math/borel-cantelli.html 1. 集序列的 lim ⁡ inf ⁡ \lim\inf liminf 和 lim ⁡ sup ⁡ \lim\sup limsup 类似于定义实数序列 { a k } \{a_k\} {ak​} 的 lim ⁡ inf ⁡ \lim\inf liminf 和 lim ⁡ sup ⁡ \lim\sup limsup, …

nginx+nginx-http-flv-module在Linux服务器搭建

需求 在服务器搭建点播/视频平台的话需要在服务器搭建nginx和rtmp模块 rtmp模块 rtmp 模块有 nginx-rtmp-module ,但是我们这里使用 nginx-http-flv-module 来替代。因为后者是基于前者开发的,前者拥有的功能后者都有,后者是国内的开发开…