2015-12-26 4 views
1

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

Как я могу это сделать?

+0

Как один получить пинту в кварт горшок - http://idioms.thefreedictionary.com/put+a+quart+into+a+pint+pot - Знак важно –

+0

Обратитесь к банковской выписке для полной информации –

ответ

2

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

u = i; 

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

uint8_t u = i; 

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


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


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


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

+0

Целочисленная упаковка без знака определяется стандартом, независимо от целочисленного представления. (Подписанная упаковка отсутствует.) –

+0

@JonPurdy: бит, который вы, кажется, не видите в своем представлении, состоит в том, что стандарт позволяет деревьям разные подписанные представления, из которых только один гарантирует сохранение битпаттерна при преобразовании значения в соответствующий неподписанный тип. –

+0

Ах, вы правы, я потерял контекст вопроса, читая ваш ответ. Это то, что я получаю за слишком много вкладок. Тем не менее, стоит отметить, что просто инициализация значения без знака из знакового значения не делает никаких предположений для конкретной платформы. –

0

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

int8_t i = something; 
uint8_t u = i; 

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

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

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

и С11 7.20.1.1/1 (С99 7.18.1.1):

название ЬурейеЕ intN_t обозначает целочисленный тип с шириной N, без заполнения битов, и представления дополняют до двух.


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

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

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

+0

Просьба указать источник для «тех типов, которые необходимы для использования представления дополнений 2». –

+0

@ Cheersandhth.-Alf добавил –

+0

Спасибо, я не видел этого в C99 и не знал, что он был добавлен. –

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; 


}