如何根据位将有符号整数值转换为无符号整数值

How to turn a signed integer value to unsigned, according to its bits?

本文关键字:整数 转换 无符号整数 符号 何根      更新时间:2023-10-16

我想把一个有符号的值变成一个无符号的值(例如,int8_tuint8_t),但它也必须保留它的位。

我该怎么做?

在实践中:您可以简单地将带符号的值分配给uint8_t

u = i;

或者你可以用带符号的值初始化它

uint8_t u = i;

这假设了二的补码有符号整数表示,这在今天是普遍使用的。通过该表示,比特被精确地保留。“在实践中";资格是指这种假设。


例如,在现代机器上,例如−42的8位有符号表示是位模式号−42+256,即(位模式号)214。标准保证将其转换为无符号,以产生相同的模256值。所以它是相同的位模式,即位模式214。


从有符号到无符号是标准定义的,尽管比特模式(1)的保留通常只是一种实际效果(所有现代计算机都是这样设计的)。但是,如果无法表示无符号值,则相反的方向会遇到编译器特定的效果。这种转换需要更加小心,因为这是编译器的自由裁量权问题,而不是硬件级别的实际保证。


(1) 正如M.M.在他的回答中所解释的那样,你的例子中的特定有符号类型int8_t是一种,因为C11在C中保证了2的补码。我在C99标准的最终草案中没有看到这种语言,所以它可能不在C99中,因此也不在基于C99的C++11或C++14中,但可能在基于C11的C++17中。

使用intN_t类型,您可以简单地编写:

int8_t i = something;
uint8_t u = i;

因为这些类型需要使用2的补码表示,其中定义此转换是为了保留位。

参考:C++14[cstulpt.syn]/2:

标题定义了所有功能、类型和宏,与C标准中的7.18相同

和C11 7.20.1.1/1(C99 7.18.1.1):

typedef名称intN_t指定一个带符号整数类型,宽度为N,没有填充位,表示为2的补码。


要保留其他整数类型的表示,请使用:

int i = something;
unsigned int i = *(unsigned int *)&i;

您可以对任何一对相应的有符号和无符号类型执行此操作。除了生成陷阱表示的可能性之外,它是安全的。

尝试显式类型转换。使用static_cast的(不安全的)类型转换对于获取变量的"原始字节"是必要的。要将的值转换为给定的类型,您可以编写以下内容:

static_cast<type_to_convert_to>(expression)

使用static_cast,在编译时静态检查cast。

#include <iostream>

int main() {
    int8_t i {11};
    uint8_t i2 = static_cast<uint8_t>(i);
    std::cout << "i occupies " <<  sizeof(i) << " bytes." << std::endl;
    std::cout << "i2 occupies " << sizeof(i2) << " bytes." << std::endl;

}