Mask calculation macro
We have a bunch of C macros here for using the preprocessor to perform operations on bit fields, and we fire warnings when trying to use those macros in visual studio. The problem can be demonstrated very easily:
#define BITFIELD_WIDTHMASK(Width) \
((Width) >= 32 ? ~0x0ul : (1ul << (Width)) - 1)
unsigned long foo(void)
{
return BITFIELD_WIDTHMASK(32);
}
Compiling this with MSVC gives a warning:
test.c(12) : warning C4293: '<<' : shift count negative or too big, undefined behavior
This is not a behavior issue - the operator <<
will not be used in this case and must be detected at compile time. But are there any suggestions on how to rewrite the macro to avoid the warning? Or, otherwise, how to redesign the macro interface for this?
Thanks in advance
a source to share
The preprocessor, not the compiler, evaluates the expression when Width is a literal constant, and it is too dumb not to evaluate both sides of the?: Expression. I guess because it doesn't handle it at all, but rather inserts an expression ?: With constant operands!
If zero width is not required, the following simplification, which works from 1 to 32:
#define BITFIELD_WIDTHMASK(Width) (~0ul >> (32-(Width)))
It seems to me that if you know the width is zero (perhaps to turn off the feature), which is implicit if you are using a constant with a constant value, it would be wise to just use zero and not reference the macro.
a source to share