Я хочу превратить подписанное значение в неподписанное (например, int8_t
в uint8_t
), но также он должен держать свои биты.
Как мне это сделать?
На практике: вы можете просто присвоить подписанное значение 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.
С 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;
Вы можете сделать это с любой парой соответствующих типов со знаком и без знака. Это безопасно, за исключением возможности генерирования представления ловушки.
Попробуйте с явным преобразованием типов. Преобразование (небезопасного) типа с использованием 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;}