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

C 如何测试有符号或无符号整数的最高有效位?,c,integer-overflow,twos-complement,C,Integer Overflow,Twos Complement,给定一个保证为某种整数的时钟数据类型,如何使用可移植C代码测试最高有效位的值?换句话说,我需要这个函数的定义: bool is_msb_set(clock_t clock); 但这里有一个转折点:你不知道时钟的大小,也不知道它是有符号的还是无符号的,但假设有符号是两个人的赞美 我的第一个想法是这样做: const clock_t MSB = 1 << ((sizeof(clock_t) * 8) - 1); bool is_msb_set(clock_t value) {

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

bool is_msb_set(clock_t clock);
但这里有一个转折点:你不知道时钟的大小,也不知道它是有符号的还是无符号的,但假设有符号是两个人的赞美

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

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);
}
如果>>运算符的左侧有符号类型和负值,则生成的值由实现定义,请参阅

因为我们假设有符号是两个互补,所以我可以测试如果值小于0,最高有效位将始终设置为1。如果它不是负的,它是正的,并且时钟是有符号的,那么>>是正确定义的

如果clock_t是无符号的,那么值<0将始终返回0,并且很可能应该由编译器进行优化


如果clock_t不是整数类型,例如,如果它是浮点或双精度,则代码不应编译,因为>>的操作数需要整数类型。因此,它只适用于整数类型

无需遮罩即可直接测试数值:

bool is_msb_set(clock_t value) {
    if (value < 0) return 1;
    return value >> (sizeof(clock_t) * CHAR_BIT - 1);
}
如果>>运算符的左侧有符号类型和负值,则生成的值由实现定义,请参阅

因为我们假设有符号是两个互补,所以我可以测试如果值小于0,最高有效位将始终设置为1。如果它不是负的,它是正的,并且时钟是有符号的,那么>>是正确定义的

如果clock_t是无符号的,那么值<0将始终返回0,并且很可能应该由编译器进行优化


如果clock_t不是整数类型,例如,如果它是浮点或双精度,则代码不应编译,因为>>的操作数需要整数类型。因此,它只适用于整数类型

你能做的就是把它转换成一个整数,这个整数保证足够大,那么,long?然后对1进行测试,你能做的就是把它转换成一个整数,保证它足够大,那么,long?然后对1进行测试,我想我们可以先检查时钟是有符号的还是无符号的,然后进行相应的测试

bool是_msb_setclock_t值{ 如果时钟_t-1<0{ /*时钟已签名*/ 返回值<0; }否则{ /*时钟没有信号*/ 返回值>1^值; } }
我想我们可以先检查一下时钟是有符号的还是无符号的,然后再进行相应的处理

bool是_msb_setclock_t值{ 如果时钟_t-1<0{ /*时钟已签名*/ 返回值<0; }否则{ /*时钟没有信号*/ 返回值>1^值; } }
只需将MSB设为uintmax,而不是clock,并强制转换为1,然后再进行明显的移位。您从哪里得到它保证为整数。?时钟可以是浮动类型。因此,很难找到最重要的位,因为&bit操作不起作用。您应该使用CHAR_bit而不是8来表示字符的大小(以位为单位)。h@GreenTree:如果我遇到一个时钟为浮点的端口,我会给它自己的实现。到目前为止,在我支持的所有系统中,clock_t都是类似整数的。只需将MSB设为uintmax_t,而不是clock_t并强制转换为1,然后再明显地进行转换。您从哪里得到它保证是整数。?时钟可以是浮动类型。因此,很难找到最重要的位,因为&bit操作不起作用。您应该使用CHAR_bit而不是8来表示字符的大小(以位为单位)。h@GreenTree:如果我遇到一个时钟为浮点的端口,我会给它自己的实现。到目前为止,在我支持的所有系统中,时钟都是类似整数的。右移导致实现定义的负值行为右移。。嗯,如果我愿意呢?不,这将改变值。因此,这仅适用于值>0的情况。好吧,假设它是两个补码,我可以加上如果值<0返回1我想你的答案是正确的:如果>>操作符复制符号位,你得到所有的,作为布尔值是正确的。如果>>运算符移位为零,则得到1,这也是正确的。我认为您可以消除<0测试的值。如果>>运算符复制符号位-我不了解该部分。>>执行除法。我无法消除<0的值,因为执行1将导致0b10010101,即符号位保持不变。定义的实现意味着它可以返回任何内容。它可以是全零,也可以是所有值的全一。这取决于实施。我不相信它,我不希望实现返回任何有意义的东西。不,我不能掩饰,之后我什么也做不了。如果值为有符号且为负数,则值>>。。。就我而言,可以返回一个随机数。右移原因
s实现定义的负值行为正确。。嗯,如果我愿意呢?不,这将改变值。因此,这仅适用于值>0的情况。好吧,假设它是两个补码,我可以加上如果值<0返回1我想你的答案是正确的:如果>>操作符复制符号位,你得到所有的,作为布尔值是正确的。如果>>运算符移位为零,则得到1,这也是正确的。我认为您可以消除<0测试的值。如果>>运算符复制符号位-我不了解该部分。>>执行除法。我无法消除<0的值,因为执行1将导致0b10010101,即符号位保持不变。定义的实现意味着它可以返回任何内容。它可以是全零,也可以是所有值的全一。这取决于实施。我不相信它,我不希望实现返回任何有意义的东西。不,我不能掩饰,之后我什么也做不了。如果值为有符号且为负数,则值>>。。。就我而言,你可以返回一个随机数。为什么你认为long会足够大?当然不是在大多数系统上…@StaceyGirl是对的:在这个特殊情况下,time.h在ubuntu上,clock_t是8字节。为什么你认为long会足够大?当然不是在大多数系统上…@StaceyGirl是对的:在这个特殊情况下,time.h在ubuntu上,时钟是8字节。我喜欢。我的一个点缀:const bool IS_SIGNED=clock_t-1<0;,然后在函数体中对use进行签名。但可能编译成相同的代码。我喜欢。我的一个点缀:const bool IS_SIGNED=clock_t-1<0;,然后在函数体中对use进行签名。不过,可能编译成相同的代码。