C宏创建位域定义

pho*_*594 4 c macros c-preprocessor

问题

我正在做一些固件编码,并有很多位掩码来管理.到目前为止,我一直在为每个要掩盖的字段重复相同的块,如下所示:

#define LinkStateMask  0x1
#define LinkStateShift 8
#define LinkState(x)  (((x) >> LinkStateShift) & LinkStateMask)
Run Code Online (Sandbox Code Playgroud)

请注意,这些字段通常是多位字段,因此并不总是保证掩码0x1.最终的宏可以很容易地在代码中使用,这是我非常喜欢的:

if( LinkState(temp) == 0 ) {
    // Link is down, return error
    return -ENODEV;
}
Run Code Online (Sandbox Code Playgroud)

问题

有没有办法让C预处理器为我生成这些宏?我知道预处理器只能在一次通过中工作,所以宏不能直接定义另一个,但希望还有另一种方法.

理想情况下,我想写一些类似于以下内容的东西,并使用与上面第二个清单相同的C代码:

BIT_FIELD(LinkState, 8, 0x1)         // BIT_FIELD(name, lsb, mask)
Run Code Online (Sandbox Code Playgroud)

对我来说,关键是在主C文件中保留符号命名的函数式用法,而不必在BIT_FIELD(...)每次需要生成掩码时编写整个调用(其中一些字段被广泛使用,导致维护噩梦).

最后一个限制:我需要的字段稀疏地分散在数百个寄存器中.如果可能的话,我真的想避免struct为每个人定义一个,因为我通常只需要一个或两个字段.

小智 5

宏不能定义另一个宏,但它可以调用另一个宏(预处理器不会停止,直到没有非终端为止)

那么,这样的事情怎么样?至少节省一些打字......

#include <stdio.h>

#define SHIFTMASK(x,s,m) (((x) >> (s)) & (m))

#define LinkState(x) SHIFTMASK(x, 8, 0x1)
#define Whatever(x) SHIFTMASK(x, 9, 0x7)

int test[] = { 0x0f00, 0x0a01, 0x0100, 0x0007 };

int main()
{
    int i;

    for (i = 0; i < 4; ++i)
    {
        printf("test[%d]: 0x%x\n", i, test[i]);
        printf("LinkState(test[%d]): 0x%x\n", i, LinkState(test[i]));
        printf("Whatever(test[%d]): 0x%x\n", i, Whatever(test[i]));
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)