简体   繁体   English

在 C 中读写整数最高位的最便携方法是什么?

[英]What is the most portable way to read and write the highest bit of an integer in C?

What is the most portable way to read and write the highest bit of an integer in C?在 C 中读写整数最高位的最便携方法是什么?

This is a Bloomberg interview question.这是彭博采访的问题。 I didn't give best answer at that time.我当时没有给出最佳答案。 Can anyone please answer it?请问有人可以回答吗?

If the type is unsigned, it's easy:如果类型是无符号的,则很容易:

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

For signed values, I know no way.对于有符号的值,我不知道。 If you find a way, it would answer several unanswered questions on SO:如果您找到方法,它将回答有关 SO 的几个未解答的问题:

C question: off_t (and other signed integer types) minimum and maximum values C 问题:off_t(和其他有符号整数类型)最小值和最大值

Is there any way to compute the width of an integer type at compile-time? 有没有办法在编译时计算整数类型的宽度?

Maybe others.也许其他人。

First, note that there's no portable way to access the top bit if we're talking about signed integers;首先,请注意,如果我们谈论的是有符号整数,则没有可移植的方式来访问最高位; there's simply no single portable representation defined in the standard, so the meaning of 'top bit' can in principle vary.标准中根本没有定义单一的可移植表示,因此“最高位”的含义原则上可能会有所不同。 Additionally, C does not allow direct access to the bitwise representation;此外,C 不允许直接访问按位表示; you can access the int as a char buffer, but you have no idea where the 'top bit' is located.您可以将 int 作为char缓冲区访问,但您不知道“最高位”位于何处。

If we're only concerned with the non-negative range of a signed integer, and assuming said range has a size that is a power of two (if not, then we need to care about the signed representation again):如果我们只关心有符号整数的非负范围,并假设该范围的大小是 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)

A similar approach can be used with unsigned ints, where it can be used to get the true top bit.类似的方法可以用于无符号整数,它可以用来获取真正的最高位。

Here's a silly one, using:这是一个愚蠢的,使用:

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. 

First attempt:第一次尝试:

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

Note: it's a quirk of C that functions specifying int or unsigned int parameters can be called with the other type without warning.注意:这是 C 的一个怪癖,指定intunsigned int参数的函数可以在没有警告的情况下用其他类型调用。 But, this probably involves a conversion - the C++ Standard 4.7.2 says:但是,这可能涉及转换 - C++ 标准 4.7.2 说:

If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type).如果目标类型是无符号的,则结果值是与源整数一致的最小无符号整数(模 2n,其中 n 是用于表示无符号类型的位数)。 [Note: In a two's complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). [注意:在二进制补码表示中,这种转换是概念性的,位模式没有变化(如果没有截断)。 ] ]

Which implies that the bit pattern may be changed if it's not a two's complement representation, which would stop this "solution" working reliably too.这意味着如果位模式不是二进制补码表示,则可能会更改位模式,这也会阻止此“解决方案”可靠地工作。 :-( :-(

Chris's comment below provides a solution (incorporated here as a function rather than preprocessor macro): Chris 下面的评论提供了一个解决方案(在此处合并为一个函数而不是预处理器宏):

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

What's wrong with this one?这个有什么问题吗?

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

It takes care of endianness, number of bits in a byte, and works also on 1's complement.它负责字节序、字节中的位数,并且也适用于 1 的补码。

#define HIGH_BIT(inttype) (((inttype)1) << (CHAR_BIT * sizeof(inttype) - 1))

example usage:用法示例:

ptrdiff_t i = 4711;
i |=  HIGH_BIT(ptrdiff_t);  /* set high bit */
i &= ~HIGH_BIT(ptrdiff_t);  /* clear high bit */

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM