Как превратить целочисленное значение со знаком в беззнаковое, в соответствии с его битами?

Я хочу превратить подписанное значение в неподписанное (например, int8_t в uint8_t), но также он должен держать свои биты.

Как мне это сделать?

1

Решение

На практике: вы можете просто присвоить подписанное значение uint8_t,

u = i;

или вы можете инициализировать его со значением со знаком,

uint8_t u = i;

Это предполагает дополнение двух целочисленное представление со знаком, которое сегодня используется повсеместно. При таком представлении биты сохраняются точно. Квалификация «на практике» относится к этому допущению.


Например, на современной машине 8-битное представление со знаком, например, −42, это номер битового шаблона −42 + 256, который (номер битового шаблона) 214. Преобразование этого значения в беззнаковый является гарантированным стандартом для получения того же значения по модулю 256. Таким образом, это тот же битовый шаблон, а именно битовый шаблон 214.


Переход от подписи к неподписанию хорошо определен стандартом, хотя сохранение битовой комбинации (1)как правило, это просто практический эффект (все современные компьютеры спроектированы таким образом). Однако, идя в противоположном направлении, вы сталкиваетесь с конкретными для компилятора эффектами, если значение без знака не может быть представлено. Это преобразование требует большей осторожности, потому что это вопрос усмотрения компилятора, а не практическая гарантия на аппаратном уровне.



(1) Как М.М. объясняет в его ответ конкретный тип со знаком в вашем примере, int8_tявляется тем, что, поскольку C11 было гарантировано два дополнения в C. Я не вижу этот язык в окончательном проекте стандарта C99, поэтому, вероятно, его не было в C99, и, следовательно, нет ни в C ++ 11, ни в C +. +14, которые основаны на C99, но, вероятно, есть в C ++ 17, который, я считаю, основан на C11.

2

Другие решения

С intN_t типы вы можете просто написать:

int8_t i = something;
uint8_t u = i;

потому что эти типы должны использовать представление дополнения 2, где это преобразование определено для сохранения битов.

Ссылка: C ++ 14 [cstdint.syn] / 2:

Заголовок определяет все функции, типы и макросы так же, как 7.18 в стандарте C.

И C11 7.20.1.1/1 (C99 7.18.1.1):

Имя определения типа intN_t обозначает целочисленный тип со знаком с шириной Nбез дополнительных битов и представления дополнения до двух.


Чтобы сохранить представление для других целочисленных типов, используйте:

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

Вы можете сделать это с любой парой соответствующих типов со знаком и без знака. Это безопасно, за исключением возможности генерирования представления ловушки.

0

Попробуйте с явным преобразованием типов. Преобразование (небезопасного) типа с использованием static_cast необходимо для получения «необработанных байтов» переменной.
Чтобы преобразовать значение в данный тип, вы пишете следующее:

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;}
0
По вопросам рекламы [email protected]