在GNU C中获取/设置整数最高位的最便携方法是什么

在GNU C中获取/设置整数最高位的最便携方法是什么?

这是彭博采访问题。 那个时候我没有给出最好的答案。 有人可以回答吗?

谢谢

如果类型未签名,则很容易:

(type)-1-(type)-1/2 

对于签名值,我不知道。 如果你找到了一种方法,它会回答关于SO的几个未解答的问题:

C问题:off_t(和其他有符号整数类型)的最小值和最大值

有没有办法在编译时计算整数类型的宽度?

也许其他人。

首先,请注意,如果我们谈论有符号整数,则没有可移植的方法来访问最高位; 标准中没有定义单个可移植表示,因此“顶部位”的含义原则上可以变化。 另外,C不允许直接访问按位表示; 你可以将int作为char缓冲区访问,但你不知道’top bit’的位置。

如果我们只关注有符号整数的非负范围,并假设所述范围的大小是2的幂(如果不是,那么我们需要再次关注有符号的表示):

 #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) 

类似的方法可以与无符号整数一起使用,它可以用于获得真正的顶部位。

这是一个愚蠢的,使用:

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

注意:C的一个怪癖是指定intunsigned int参数的函数可以在没有警告的情况下使用另一种类型调用。 但是,这可能涉及转换 – C ++标准4.7.2说:

如果目标类型是无符号的,则结果值是与源整数一致的最小无符号整数(模2n,其中n是用于表示无符号类型的位数)。 [注意:在二进制补码表示中,此转换是概念性的,并且位模式没有变化(如果没有截断)。 ]

这意味着如果位模式不是二进制补码表示,则可以改变位模式,这将阻止该“解决方案”也可靠地工作。 🙁

Chris的评论提供了一个解决方案(此处作为函数而非预处理器宏合并):

 int get_msb(int x) { return x ? __buildin_clz(*(unsigned*)&x) == 0 : 0; } 

这个有什么问题?

 int 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的补码。

 #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 */