如何测试有符号或无符号整数的最高有效位?
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
可以是浮动类型。为此,将很难找到最重要的位,因为&
位操作将不起作用。
您应该使用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);
如果>>
运算符的左侧有“有符号类型和负值,结果值是实现定义的”,请参阅C11 6.5.7p5。
因为我们assumed "signed" is twos-compliment
,我可以测试value
是否低于0,最高有效位将始终设置为1。如果不是负数,则为正数,并且 clock_t
已签名,则 >>
已正确定义。
如果clock_t
是无符号的,那么value < 0
将始终返回0
,并且很可能应该由编译器进行优化。
如果clock_t
不是整数类型(例如,如果它是float
或double
),则代码不应编译,因为>>
的操作数需要具有整数类型。所以它只适用于整数类型。
【讨论】:
右移会导致实现定义的负值行为 对.. 嗯,如果我要abs(value)
会怎样?不,这会改变价值。所以这只适用于value > 0
。好吧,假设它是二进制补码,我可以添加 if (value < 0) return 1
我认为你的答案有效:如果 >> 运算符复制符号位,你会得到所有的,因为布尔值是真的。如果 >> 运算符移入零,则得到 1,这也是正确的。 (而且我认为您可以消除 (value < 0)
测试。)
if the >> operator copies the sign bit
- 我不明白那部分。 >>
执行除法。我无法消除value < 0
,因为对带有负值的签名类型执行<<
是实现定义的。我完全相信有一个实现,例如(int8_t)0b10101010 >> 1
导致0b10010101
,即。符号位保持不变。
实现定义意味着它可以返回任何东西。对于所有值,它可以是全零或全一。这取决于实施。我不相信它,我不希望实现返回任何“有意义”的东西。不,我不能掩饰它,在那之后我什么也做不了。如果value
有符号且为负数,则value >> (...)
可以返回我所关心的随机数。【参考方案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 < 0;
,然后在函数体中使用 IS_SIGNED。不过,可能会编译成相同的代码。【参考方案3】:
你可以做的是将它转换为一个保证足够大(所以,长?)的整数,然后然后对1 << ((sizeof(clock_t) * 8) - 1);
进行测试。
我也会首先断言sizeof(clock_t) <= sizeof(long)
。
【讨论】:
为什么你认为long
会足够大?它当然不在大多数系统上......
@StaceyGirl 是对的:在这种特殊情况下(ubuntu 上的 time.h),clock_t 是 8 个字节。以上是关于如何测试有符号或无符号整数的最高有效位?的主要内容,如果未能解决你的问题,请参考以下文章
2021-09-11:给你一个32位的有符号整数x,返回将x中的数字部分反转后的结果。反转后整数超过 32 位的有符号整数的范围就返回0,假设环境不允许存储 64 位整数(有符号或无符号)。(代码片段