我想将有符号值转换为无符号值(例如int8_t
to uint8_t
),但它也必须保留其位。
我该怎么做?
在实践中:您可以简单地将带符号的值分配给uint8_t
,
u = i;
或者您可以使用带符号的值对其进行初始化,
uint8_t u = i;
这假定了一个二进制补码有符号整数表示,这在今天普遍使用。使用该表示,位被准确地保留。“在实践中”的限定是指该假设。
例如,在现代机器上,例如 -42 的 8 位有符号表示是位模式编号 -42 + 256,即(位模式编号)214。标准保证将其转换为无符号以产生相同的模 256 .所以它是相同的bitpattern,即bitpattern 214。
标准很好地定义了从有符号到无符号的转换,尽管位模式(1)的保留通常只是一种实践效果(所有现代计算机都是这样设计的)。但是,如果无法表示无符号值,则相反,您会遇到编译器特定的效果。这种转换需要更加小心,因为这是编译器自行决定的问题,而不是硬件级别的实际保证。
(1) 正如 MM 在他的回答中解释的那样,您的示例中的特定有符号类型int8_t
, 是因为 C11 在 C 中得到保证的二进制补码。我在 C99 标准的最终草案中没有看到这种语言,所以大概是在 C99 中不存在,因此在基于 C99 的 C++11 或 C++14 中也不存在,但在我认为基于 C11 的 C++17 中可能存在。
使用这些intN_t
类型,您可以简单地编写:
int8_t i = something;
uint8_t u = i;
因为这些类型需要使用 2 的补码表示,其中定义此转换以保留位。
参考:C++14 [cstdint.syn]/2:
头文件定义了与 C 标准中的 7.18 相同的所有函数、类型和宏
和 C11 7.20.1.1/1 (C99 7.18.1.1):
typedef 名称
intN_t
指定一个有符号整数类型,其宽度N
、无填充位和二进制补码表示。
要保留其他整数类型的表示,请使用:
int i = something;
unsigned int i = *(unsigned int *)&i;
您可以使用任何一对对应的有符号和无符号类型来执行此操作。除了可能生成陷阱表示之外,它是安全的。
尝试显式类型转换。使用 static_cast 的(不安全的)类型转换对于获取变量的“原始字节”是必要的。要将 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;
}