Гарантирует ли стандарт c интерпретацию битовых комбинаций для знаков со знаком и без знака? - PullRequest
1 голос
/ 27 октября 2011

Стандарт C указывает, как должны интерпретироваться битовые представления?Другими словами, следует ли делать следующее, если условия всегда оцениваются как истинные?Предположим, sizeof (int) = 4 и CHAR_BIT = 8

unsigned u = 0xffffffff;
if (u == 4294967295) /* do something */

int i = 0xffffffff;
if (i == -1) /* do something */

unsigned u = (int)0xffffffff;
if (u == 0xffffffff) /* do something */

int i = hex_literal;
unsigned u;
memcpy (&u, &i, sizeof (u));
if (i == u) /* do something */
if ((i & 0x7fffffff) == (u & 0x7fffffff)) /* do something */

int i = hex_literal;
unsigned u = i;
if (i == u) /* do something */

unsigned u = hex_literal;
int i = u;
if (i == u) /* do something */

int i = hex_literal;
unsigned u = hex_literal;
if (i == hex_literal && u == hex_literal) /* do something */

char c = 0xff;
if (c >> 4 == 0xf) /* do something */

signed char c = 0xff;
if (((c >> 4) & 0xff) == 0xf) /* do something */

Ответы [ 4 ]

2 голосов
/ 27 октября 2011

Я сделаю дополнительное предположение, что ни один тип не имеет битов заполнения в обсуждаемой реализации.Давайте рассмотрим их по одному:

unsigned u = 0xffffffff;
if (u == 4294967295) /* do something */

Да.

int i = 0xffffffff;
if (i == -1) /* do something */

Нет.Преобразование числа вне диапазона в тип со знаком дает результат, определенный реализацией.

unsigned u = (int)0xffffffff;
if (u == 0xffffffff) /* do something */

Нет, та же причина, что и в предыдущем примере.

int i = hex_literal;
unsigned u;
memcpy (&u, &i, sizeof (u));
if (i == u) /* do something */
if ((i & 0x7fffffff) == (u & 0x7fffffff)) /* do something */

Да.Стандарт гарантирует, что каждый бит значения в типе со знаком имеет одинаковое значение в объектном представлении соответствующего типа без знака.

int i = hex_literal;
unsigned u = i;
if (i == u) /* do something */

Да.Повышение i с int до unsigned является детерминированным и дает одинаковое значение как в присваивании u, так и в сравнении.

unsigned u = hex_literal;
int i = u;
if (i == u) /* do something */

Да, но только если hex_literal находится в диапазоне (положительных) значений, представляемых int - в противном случае результат, определенный реализацией, снова наносит удар.

int i = hex_literal;
unsigned u = hex_literal;
if (i == hex_literal && u == hex_literal) /* do something */

u == hex_literal всегда будет иметь значение true, но i == hex_literal нужно толькосделайте это, если hex_literal находится в диапазоне значений, представляемых int.

char c = 0xff;
if (c >> 4 == 0xf) /* do something */

char может быть подписано или не подписано.Если он не подписан, то тест будет верным;если подписано, то c и c >> 4 будут иметь значения, определенные реализацией, поэтому это может быть неверно.

signed char c = 0xff;
if (((c >> 4) & 0xff) == 0xf) /* do something */

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

Обратите внимание, что все ваши вопросы, кроме memcpy(), относятся только к значениям , а не к представлению .

2 голосов
/ 27 октября 2011

Для неподписанных, да. Для подписанных типов нет; стандарт допускает 2 дополнения, 1 дополнение или представления величины знака. Соответствующий раздел стандарта (C99) - 6.2.6.2.

Отдельная проблема заключается в том, что код, такой как unsigned u = (int)0xffffffff, вызывает неопределенное поведение, поскольку это вызывает переполнение целых чисел (раздел 6.3.1.3).

Еще одна проблема заключается в том, что такой код, как char c = 0xff; c >> 4, определяется реализацией по двум причинам. Во-первых, char может быть либо signed, либо unsigned. Во-вторых, если это signed, то смещение вправо отрицательного числа определяется реализацией (раздел 6.5.7).

1 голос
/ 27 октября 2011

Беззнаковые числа имеют гарантированную арифметику по модулю 2 ^ n. Для подписанных таких гарантий нет.

Ничего не сказано о битовых шаблонах. Обратите внимание, что 0xfffffff не является «битовой комбинацией», это число (чьи «битовые комбинации» не имеют значения для стандарта C ++), которое гарантированно удовлетворяет x + 1 = 0, если x является 32-битным числом без знака который вы присвоили 0xffffffff.

0 голосов
/ 27 октября 2011

Ключевым элементом для запоминания является то, что шестнадцатеричные литералы (например, 0x0F) относятся к значению (здесь: 15), а не к порядку, в котором биты и байты хранятся физически.

Зависит от машины то, как это хранится - одни сначала будут хранить младший бит, другие - старший бит, а AFAIK на x86 - наименее значимый байт первый, но старший бит первый.

Но всегда верно, что 0x000F равно 15.

...