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

Posted

技术标签:

【中文标题】如何测试有符号或无符号整数的最高有效位?【英文标题】:How to test the most significant bit of signed or unsigned integer? 【发布时间】:2019-11-03 23:06:16 【问题描述】:

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

bool is_msb_set(clock_t clock);

但这里有个转折点:你不知道clock_t 的大小,也不知道它是有符号的还是无符号的(但假定“有符号”是双恭维)。

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

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

bool is_msb_set(clock_t value) 
    return value & MSB;

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

【问题讨论】:

只需将 MSB 设为 uintmax_t 而不是 clock_t(并在明显移动之前转换为 1 你从哪里得到它保证是一个整数。? > clock_t 可以是浮动类型。为此,将很难找到最重要的位,因为&amp; 位操作将不起作用。 您应该使用CHAR_BIT 而不是8 来表示char 的大小(来自limits.h) @GreenTree:如果我遇到clock_t 是浮点数的端口,我会给它自己的实现。在我支持的所有系统中(到目前为止),clock_t 类似于整数。 【参考方案1】:

不带掩码直接测试值:

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

如果&gt;&gt; 运算符的左侧有“有符号类型和负值,结果值是实现定义的”,请参阅C11 6.5.7p5。

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

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

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

【讨论】:

右移会导致实现定义的负值行为 对.. 嗯,如果我要abs(value) 会怎样?不,这会改变价值。所以这只适用于value &gt; 0。好吧,假设它是二进制补码,我可以添加 if (value &lt; 0) return 1 我认为你的答案有效:如果 >> 运算符复制符号位,你会得到所有的,因为布尔值是真的。如果 >> 运算符移入零,则得到 1,这也是正确的。 (而且我认为您可以消除 (value &lt; 0) 测试。) if the &gt;&gt; operator copies the sign bit - 我不明白那部分。 &gt;&gt; 执行除法。我无法消除value &lt; 0,因为对带有负值的签名类型执行&lt;&lt; 是实现定义的。我完全相信有一个实现,例如(int8_t)0b10101010 &gt;&gt; 1 导致0b10010101,即。符号位保持不变。 实现定义意味着它可以返回任何东西。对于所有值,它可以是全零或全一。这取决于实施。我不相信它,我不希望实现返回任何“有意义”的东西。不,我不能掩饰它,在那之后我什么也做不了。如果value 有符号且为负数,则value &gt;&gt; (...) 可以返回我所关心的随机数。【参考方案2】:

我认为我们可以先检查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;
    

【讨论】:

我喜欢。我的一个点缀:const bool IS_SIGNED = (clock_t)-1 &lt; 0;,然后在函数体中使用 IS_SIGNED。不过,可能会编译成相同的代码。【参考方案3】:

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

我也会首先断言sizeof(clock_t) &lt;= sizeof(long)

【讨论】:

为什么你认为long 会足够大?它当然不在大多数系统上...... @StaceyGirl 是对的:在这种特殊情况下(ubuntu 上的 time.h),clock_t 是 8 个字节。

以上是关于如何测试有符号或无符号整数的最高有效位?的主要内容,如果未能解决你的问题,请参考以下文章

2021-09-11:给你一个32位的有符号整数x,返回将x中的数字部分反转后的结果。反转后整数超过 32 位的有符号整数的范围就返回0,假设环境不允许存储 64 位整数(有符号或无符号)。(代码片段

ARTS Week 6

如何将两个32位整数组合成一个64位整数?

算法刷题:LC初级算法

算法刷题:LC初级算法

如何表示“大于 T 的最小整数类型”?