如何根据其位将有符号整数值转换为无符号整数?
How to turn a signed integer value to unsigned, according to its bits?
我想把一个有符号的值变成一个无符号的值(例如,int8_t
到 uint8_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;
}
我想把一个有符号的值变成一个无符号的值(例如,int8_t
到 uint8_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 widthN
, 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;
}