在C语言中,读写整数的最高位最便携的方法是什么?
这是Bloomberg的面试问题。当时我没有给出最好的答案。请问有人能回答吗?
在C语言中,读写整数的最高位最便携的方法是什么?
这是Bloomberg的面试问题。当时我没有给出最好的答案。请问有人能回答吗?
(type)-1-(type)-1/2
对于有符号值,我不知道任何方法。如果你找到了一种方法,它将回答 SO 上几个未解决的问题:
也许还有其他问题。
(unsigned)-1-(unsigned)-1/2
给出了预期的0x80000000
。 - R.. GitHub STOP HELPING ICE~((unsigned)-1 >> 1)
。 - Christoph(type)-1 - (type)-1 / 2
,答案更易读... :-/. - Tony Delroy#define INT_MAX_BIT (INT_MAX - (INT_MAX >> 1))
#define SET_MAX_BIT(x) (x | INT_MAX_BIT)
#define CLEAR_MAX_BIT(x) (x & ~INT_MAX_BIT)
类似的方法也可以用于无符号整数,它可以用来获取真正的最高位。
limits.h
中指定了限制的整数类型。例如,对于 off_t
,它无效。 - R.. GitHub STOP HELPING ICEINT_MAX
的值具有所有 1 设置(假定对于某些 n,INT_MAX 等于 2^n-1)。右移一位会导致最高位被清除。然后从原始值中减去仅留下最高位设置。 - bdonlan2 ** N - 1
。请参见第6.2.6.2节。 - cafBuilt-in Function: int __builtin_clz (unsigned int x)
Returns the number of leading 0-bits in x, starting at the most
significant bit position. If x is 0, the result is undefined.
第一次尝试:
int get_msb(int x) { return x ? __buildin_clz(x) == 0 : 0; }
int
或unsigned int
参数的函数可以在不警告的情况下使用另一种类型进行调用,这是C语言的一个怪癖。但是,这可能涉及到转换——C++标准4.7.2表示:
如果目标类型为无符号类型,则结果值是与源整数同余的最小无符号整数(模2n,其中n是用于表示无符号类型的位数)。[注意:在二进制补码表示中,这种转换是概念性的,如果没有截断,位模式不会改变。]
这意味着如果它不是二进制补码表示,则位模式可能会被更改,这也将使这个“解决方案”无法可靠地工作。 :-(
克里斯的下面评论提供了一个解决方案(这里作为函数而不是预处理器宏):
int get_msb(int x) { return x ? __buildin_clz(*(unsigned*)&x) == 0 : 0; }
#define msb(x) __builtin_clz(*(unsigned)&x)
,但这样你就不能在字面数字上使用它。GCC 的解决方法是 #define msb(x) ({ typeof(x) _x = x; __builtin_clz(*(unsigned)&_x); })
。 - Chris Lutzint x
参数将会接收字面量,然后你可以按照你所建议的进行转换。我会更新上面的代码。谢谢! - Tony Delroyunion { int i; unsigned u; } u; u.i = x; return __builtin_clz(u.j);
一样。我使用了一个宏,这样它就可以适用于有符号和无符号的 int
类型,并仅为有符号版本调用 UB。但是,无论如何,你做什么都会变得必然依赖于平台。 - Chris Lutzint get_msb(int n){
return ((unsigned)n) >> (sizeof(unsigned) * CHAR_BIT - 1);
// or, optionally
return n < 0;
};
int set_msb(int n, int msb){
if (msb)
return ((unsigned)n) | (1ULL << (sizeof(unsigned) * CHAR_BIT - 1));
else return ((unsigned)n) & ~(1ULL << (sizeof(unsigned) * CHAR_BIT - 1));
};
它处理字节序、字节中的位数,并且也适用于1的补码。
sizeof(X)*CHAR_BIT
假设没有填充位。 - R.. GitHub STOP HELPING ICE#define HIGH_BIT(inttype) (((inttype)1) << (CHAR_BIT * sizeof(inttype) - 1))
使用示例:
ptrdiff_t i = 4711;
i |= HIGH_BIT(ptrdiff_t); /* set high bit */
i &= ~HIGH_BIT(ptrdiff_t); /* clear high bit */