интерпретировать неподписанный как подписанный - PullRequest
7 голосов
/ 10 сентября 2011

Я работаю на встроенной платформе (ARM) и должен быть осторожен при работе с битовыми шаблонами. Давайте представим, что эта строка вне моего влияния:

uint8_t foo = 0xCE;          // 0b11001110

Интерпретируется как неподписанное, это будет 206. Но на самом деле оно подписано, поэтому напоминает -50 . Как я могу продолжать использовать это значение как подписанное?

int8_t bar = foo;            // doesn't work

также не делает (в результате 0x10 или 0x00 для всех входных значений)

int8_t bar = static_cast<int8_t>(foo);
int8_t bar = reinterpret_cast<int8_t&>(foo);

Я просто хочу, чтобы биты остались нетронутыми, т.е. (bar == 0xCE)

И наоборот, мне было бы интересно, как получить битовые шаблоны, представляющие отрицательные числа, в беззнаковые переменные, не путая битовый шаблон. Я использую GCC.

Ответы [ 5 ]

8 голосов
/ 10 сентября 2011

Для меня нормально работает следующее: , как следует , хотя, как говорится в комментариях, это определяется реализацией:

int x = (signed char)(foo);

В C ++ вы также можете сказать:

int x = static_cast<signed char>(foo);

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

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

5 голосов
/ 10 сентября 2011
uint8_t foo = 0xCE;          // 0b11001110
int8_t bar;
memcpy( &bar, &foo, 1 );

У него даже есть дополнительный бонус: 99% компиляторов полностью оптимизируют вызов memcpy ...

3 голосов
/ 10 сентября 2011

Что-то уродливое в этом духе? ​​

int8_t bar = (foo > 127) ? ((int)foo - 256) : foo;

Не зависит от преобразования, поведение которого не определено.

0 голосов
/ 11 сентября 2011

Вы можете получить доступ к представлению значения, используя указатель. Повторно интерпретируя тип указателя, а не тип значения, вы сможете реплицировать представление.

uint8_t foo = 0xCE;          
int8_t bar = *reinterpret_cast<int8_t*>(&foo);
0 голосов
/ 10 сентября 2011

С вероятностью GCC, значения без знака являются дополнением к двум, даже на вашей встроенной платформе.

Тогда 8-битное число 0xCE представляет 0xCE-256.

Поскольку дополнение к двум на самом деле просто по модулю 2 n , где n - количество бит в представлении.

РЕДАКТИРОВАТЬ : хм, ради представителя, я бы лучше привести конкретный пример:

int8_t toInt8( uint8_t x )
{
    return (x >= 128? x - 256 : x);
}

РЕДАКТИРОВАТЬ 2 : я не видел окончательного вопроса о том, как получить битовый шаблон в беззнаковую переменную. Это очень просто: просто назначьте. Результат гарантируется стандартом C ++, а именно то, что сохраненное значение является конгруэнтным (на часовом лице равно) присвоенному значению по модулю 2 n .

Приветствия и hth.,

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...