位域掩码计算宏

时间:2010-05-04 20:02:09

标签: c macros

我们有一组C宏,在这里,使用预处理器进行位域操作,我们在尝试在visual studio中使用这些宏时会遇到警告。这个问题很容易证明:

#define BITFIELD_WIDTHMASK(Width) \
    ((Width) >= 32 ? ~0x0ul : (1ul << (Width)) - 1)

unsigned long foo(void)
{
    return BITFIELD_WIDTHMASK(32);
}

使用MSVC进行编译会产生警告:

test.c(12) : warning C4293: '<<' : shift count negative or too big, undefined behavior

这不是行为问题 - 在这种情况下不会使用<<运算符,并且应该在编译时检测到它。但有没有人有任何关于如何重写宏以避免警告的建议?或者,如果不这样做,如何为此重新设计宏接口?

提前致谢

3 个答案:

答案 0 :(得分:3)

#define BITFIELD_WIDTHMASK(Width) (((0x80000000ul >> (32-Width)) << 1) - 1)

或处理宽度0以及请求...

#define BITFIELD_WIDTHMASK(Width) \
  ((Width) >= 32 \
  ? ~0x0ul \
  : (((1ul << ((Width)/2)) << ((Width)/2)) << ((Width)&1)) - 1)

答案 1 :(得分:3)

怎么样:

#define BITFIELD_WIDTHMASK(Width) \
    ((Width) >= 32 ? ~0x0ul : (1ul << (Width % 32)) - 1)

答案 2 :(得分:1)

当Width是一个文字常量时,预处理器而不是编译器会计算表达式,并且不能评估?:表达式的双方都太愚蠢。我想因为它根本不处理它而是插入带有常量操作数的?:表达式!

如果不需要宽度为零,则以下是适用于1到32的简化:

#define BITFIELD_WIDTHMASK(Width) (~0ul >> (32-(Width)))

在我看来,如果你知道宽度为零,(可能是为了禁用一个特性),如果你使用一个文字零常量是隐含的,那么只使用零而不是调用宏是合理的。 / p>