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.