在另一个宏声明中使用宏

Using macro within another macro declaration

让我们从代码和错误开始。

#define BitMap_getMask(range)           (((~(unsigned int)0>>(31-range.b+range.a))<<range.a))
#define BitMap_get(x, range)            (x & BitMap_getMask(range))
#define awesome (range){4,6}
...................
printf("%08x\n", BitMap_get(0xEEEEEEEE, awesome));

现在是编译器的错误。第 29 行,带有 printf.

的行

error: macro "BitMap_getMask" passed 2 arguments, but takes just 1
error: 'BitMap_getMask' undeclared (first use in this function)

我正在开发一个小型库,它将帮助我进行按位运算。尝试在另一个宏中使用一个宏时出现此错误。

这可能是您需要的

#define BitMap_getMask(range) \
   (((~(unsigned int) 0 >> (31 - (range).max + (range).min)) << (range).min))

#define BitMap_get(x, range) \
   ((x) & BitMap_getMask(range))

#define awesome \
   ((struct {int min; int max;}){4, 6})

错误是由于 {4, 6} 的扩展造成的。

当范围扩展到 {4,6} 并传递给 BitMap_getMask 时,您得到的是 BitMap_getMask({4,6}) 这是 2 个参数,而 BitMap_getMask 需要 1 个参数。

此外,预处理器只对这些宏进行文本替换。它不知道类型。它将用文本“{4,6}”替换文本 "range" 的每个实例,因此您没有可以使用的类型(结构范围)或类型实例,只有一些文本,所以 "range.a" 和 "range.b" 也不起作用;他们会产生类似于“{4,6}.a”和“{4,6}.b”的结果

无效 C.

C99 支持内联函数,现在几乎没有借口在 C 中使用预处理器宏。它们很麻烦(当然,一个很好的用途是包括警卫)。内联函数在编译器的范围内并经过正确的类型检查。

struct awesome
{
    unsigned int a;
    unsigned int b;
};

...

static inline unsigned int BitMap_get(unsigned int x, awesome range) 
{
    return (x & BitMap_getMask(range));
}

static inline unsigned int BitMap_getMask(awesome range) 
{
    return (((~(unsigned int)0>>(31-range.b+range.a))<<range.a));
}

...

awesome range = 
{
    .a = 4,
    .b = 6,
};

unsigned int x = 0xEEEEEEEE;
unsigned int bm = BitMap_get(x, awesome);
...