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