fearless_fool
fearless_fool

Reputation: 35219

How to test the most significant bit of signed or unsigned integer?

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

Answers (3)

Nate Eldredge
Nate Eldredge

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

KamilCuk
KamilCuk

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

Mike Nakis
Mike Nakis

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

Related Questions