动态使用不同定义的 C 宏

标签 c macros arm embedded

我试图编写的宏的目的是更新一个传递由值、位置和长度定义的新值的字符。让我举个例子来更好地解释一下:

原始值:0b11000011 要更新的值:0b11 放置位置:4 新值的长度:2

基本上,我想在字节(0b11000011)中间放置两位(0b11)以获得新字节(0b11011011)

我现在拥有的宏类似于

#define UPDATE_REG(REG, MASK, POS, LEN, VAL) ((REG) = (((REG) & (MASK)) | (VAL<<(POS +1 -LEN))))

而且效果很好。例如,在我的标题中,我有这样的定义

#define     CP_BYP_MODE_SAD                                     0x38
#define     CP_BYP_MODE_ADR                                     0xD4
#define     CP_BYP_MODE_POS                                     4
#define     CP_BYP_MODE_LEN                                     3
#define     CP_BYP_MODE_DEF                                     0b00
#define     CP_BYP_MODE_MSK                                     0b11100111

为了使用宏,我编写了以下代码

uint8_t Reg = 0b11000011;
UPDATE_REG(Reg, CP_BYP_MODE_MSK, CP_BYP_MODE_POS, CP_BYP_MODE_LEN, 0b11);

这个解决方案效果很好,但我的观点是,我想通过一些技巧来减少参数(如果可能的话),考虑到我将在每次调用时使用由以下组成的三个定义 姓名_MSK 名称_POS name_LEN

需要明确的是,我的目标是拥有一个类似的宏

#define UPDATE_REG(REG, NAME, VAL) ((REG) = (((REG) & (**NAME_MSK**)) | (VAL<<(**NAME_POS** +1 - **NAME_LEN**))))

例如,仅通过 CP_BYP_MODE 即可获取 CP_BYP_MODE_POS,并且能够自动添加 _POS 后缀。

最佳答案

首先,确实没有必要为此编写晦涩的宏,这只会让代码更难阅读。不幸的是,人们试图将简单的按位算术隐藏在抽象层后面是很常见的,只是因为他们发现按位算术很棘手。

您应该做的是保持简单:

uint8_t reg = 0xC3; 
uint8_t mask = 0x18;
uint8_t new_val = 0x18;
reg &= ~mask; // clear values with mask
reg |= new_val; // write new value to the cleared position
<小时/>

值得注意的是,如果您知道掩码,则意味着您已经知道大小和位位置。您可以根据大小和位置计算掩模,如下所示:

mask = ((1 << size)-1) << pos;

大小 = 2,位置 = 3 给出:
1 << 2 = 0000 0100b = 0x04
0x04-1 = 0000 0011b = 0x03
0x03 << 3 = 0001 1000b = 0x18

关于动态使用不同定义的 C 宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47470362/

相关文章:

linux-kernel - 在/init 之后退出代码 = 0x00000004 的内核 panic

assembly - 关于进位标志的 ARM 文档的困惑

c - C 中的指针和数组有什么不同吗?

c++ - 它是什么? C++宏函数?怎么替换这个宏?我可以举个例子吗?

c - C语言的Socket通信。发送文件内容

regex - 使用 Enlive 和 Clojure 提取 MLA 引用的 HTML

xcode - 你如何隐藏基于宏定义的代码?

arm - 从树莓派中提取 MBR

c++ - 循环中的预递增/递减与使用 gcc 和 Visual C 的递增/递减

c - 如何在 C 中找到行指针?