如何测试有符号或无符号整数的最高有效位?

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

给定一个保证为某种整数的 clock_t 数据类型,您如何使用可移植的 C 代码测试最高有效位的值?换句话说,我需要这个函数的定义:

bool is_msb_set(clock_t clock);

但问题在于:您不知道 clock_t 的大小,也不知道它是有符号还是无符号(但假设 "signed" 是双补)。

我的第一个想法是这样做:

const clock_t MSB = 1 << ((sizeof(clock_t) * 8) - 1);

bool is_msb_set(clock_t value) {
    return value & MSB;
}

但如果 clock_t 是有符号值,则 MSB 的定义会溢出。也许我想多了,但我很难过。

不加掩码直接测试值即可:

bool is_msb_set(clock_t value) {
    if (value < 0) return 1;
    return value >> (sizeof(clock_t) * CHAR_BIT - 1);
}

如果 >> 运算符的左侧有 "a signed type and a negative value, the resulting value is implementation-defined",请参阅 C11 6.5.7p5

因为我们assumed "signed" is twos-compliment,我可以只测试value是否小于0,最高有效位将始终设置为1。如果它不是负数,则为正数,并且 clock_t 已签名,则 >> 已正确定义。

如果 clock_t 是无符号的,那么 value < 0 将始终 return 0 并且很可能应该被编译器优化掉。

如果 clock_t 不是整数类型(例如 floatdouble),则代码不应编译,因为 >> 的操作数需要有整数类型。所以它只适用于整数类型。

你可以做的是将它转换为一个保证足够大(那么长?)的整数,然后 然后1 << ((sizeof(clock_t) * 8) - 1); 进行测试。

我也会首先断言sizeof(clock_t) <= sizeof(long)

我想我们可以先检查clock_t是有符号的还是无符号的,然后据此进行。

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;
    }
}