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

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

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

我该怎么做?

实际上:您可以简单地将带符号的值分配给 uint8_t

u = i;

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

uint8_t u = i;

这假设 two's complement 有符号整数表示,这在今天被普遍使用。使用该表示,这些位将被准确保留。 “在实践中”限定是指该假设。


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


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


(1) 如M.M。在 中解释了您示例中的特定符号类型 int8_t,因为 C11 在 C 中已保证二进制补码。我在 C99 标准的最终草案中没有看到该语言,所以据推测它不存在于 C99 中,因此不存在于基于 C99 的 C++11 或 C++14 中,但可能存在于 C++17 中,我认为它基于 C11。

使用 intN_t 类型你可以简单地写:

int8_t i = something;
uint8_t u = i;

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

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

The header defines all functions, types, and macros the same as 7.18 in the C standard

和 C11 7.20.1.1/1 (C99 7.18.1.1):

The typedef name intN_t designates a signed integer type with width N, no padding bits, and a two’s complement representation.


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

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

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

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

static_cast<type_to_convert_to>(expression)

使用 static_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;


}