Reputation: 35219
Given a clock_t
data type that is guaranteed to be an integer of some sort, how do you test the value of the most significant bit using portable C code? In other words, I need the definition of this function:
bool is_msb_set(clock_t clock);
But here's the twist: you don't know the size of clock_t
nor if it is signed or unsigned (but assumed "signed" is twos-compliment).
My first thought was to do this:
const clock_t MSB = 1 << ((sizeof(clock_t) * 8) - 1);
bool is_msb_set(clock_t value) {
return value & MSB;
}
but the definition of MSB overflows if clock_t
is a signed value. Maybe I'm overthinking this, but I'm stumped.
Upvotes: 1
Views: 400
Reputation: 58473
I think we can first check whether clock_t
is signed or unsigned, and proceed accordingly.
bool is_msb_set(clock_t value) {
if ((clock_t)-1 < 0) {
/* clock_t is signed */
return value < 0;
} else {
/* clock_t is unsigned */
return ((value << 1) >> 1) ^ value;
}
}
Upvotes: 2
Reputation: 141493
Just test the value directly without a mask:
bool is_msb_set(clock_t value) {
if (value < 0) return 1;
return value >> (sizeof(clock_t) * CHAR_BIT - 1);
}
If the left side of >>
operator has "a signed type and a negative value, the resulting value is implementation-defined", see C11 6.5.7p5.
Because we assumed "signed" is twos-compliment
, I can just test if value
is lower then 0, the most significant bit will always be set to one. If it is not negative, it's positive, and clock_t
is signed then >>
is properly defined.
If clock_t
is unsigned, then value < 0
will always return 0
and most probably should be optimized out by the compiler.
The code shouldn't compile if clock_t
is not an integer type (ex. if it a float
or double
), because the operands of >>
need to have integer type. So it will only work for integer types.
Upvotes: 2
Reputation: 62045
What you can do is cast it to an integer which is guaranteed to be large enough (so, long?) and then do your test against 1 << ((sizeof(clock_t) * 8) - 1);
.
I would also start by asserting that sizeof(clock_t) <= sizeof(long)
.
Upvotes: 0