Normally you'd define this as a function and let the compiler figure out the rest, but if you're implementing it as a macro you need to consider the context.
Remember macros get expanded in the source, so they need to be syntactically valid in the context they appear. Within a function call you can't use ;
, so ,
is used instead as a substitute.
Like this function might be called:
int v = 5 + 3 << 2;
if (other_fn(kroundup(v)) { ... }
Where using ;
there would obviously break things badly. It needs ,
:
if (other_fn((--(v), (v)|=(v)>>1, (v)|=(v)>>2, (v)|=(v)>>4, (v)|=(v)>>8, (v)|=(v)>>16, ++(v))) { ... }
Now the (x)
part is a tradition to handle complex expressions:
if (other_fn(kroundup(5 + 3 << 2)) { ... }
Yet it doesn't handle those correctly due to using operators like --
that make no sense on anything but variables:
if (other_fn((--(5 + 3 << 2), (5 + 3 << 2)|=(5 + 3 << 2)>>1, ..., ++(5 + 3 << 2))) { ... }
It should be just x
in the macro to catch problems like this.
In all honesty this macro shouldn't exist, the macro is just a terrible idea because it's buggy, it impedes understanding, and you should just let the compiler inline it as a regular function it if it thinks it can, like this:
int kroundup32(x) {
--x;
x |= x>>1;
x |= x>>2;
x |= x>>4;
x |= x>>8;
x |= x>>16;
++x;
return x;
}
Where that is way more readable.