Unsigned integer и unsigned char сохраняют одинаковое значение, но по-другому ведут себя по-другому?

Почему это так, что

unsigned char k=-1
if(k==-1)

false

unsigned int k=-1
if(k==-1)

истинно

4 ответа

В целях демонстрации предположим, что 8-разрядные char и 32-разрядные int s.

unsigned char k=-1;

k присваивается значение 255.

if(k==-1)

Левая часть оператора == равна unsigned char. Правая часть имеет вид int. Поскольку все возможные значения unsigned char могут вписываться внутрь int, левая часть преобразуется в int (это выполняется из-за целых рекламных акций, приведенных ниже). Это приводит к сравнению (255 == -1), что неверно.

unsigned int k=-1

k присваивается значение 4294967295

if(k==-1)

В этот раз левая часть (неподписанный int) не может быть помещена в int. В стандарте говорится, что в этом случае оба значения преобразуются в unsigned int. Таким образом, это приводит к сравнению (4294967295 == 4294967295), что верно.

Соответствующие цитаты из стандарта:

Целочисленные акции: (C99, 6.3.1.1p2)

Если int может представлять все значения исходного типа, значение преобразуется в int; в противном случае он преобразуется в unsigned int.

Обычные арифметические преобразования: (6.3.1.8).

[Для целых операндов] целые акции выполняются на обоих операндах. Затем для продвинутых операндов применяются следующие правила: - Если оба операнда имеют один и тот же тип, то дальнейшее преобразование не требуется. ... - В противном случае, если операнд с целым типом без знака имеет ранг больше или равный рангам типа другого операнда, то операнд с целочисленный тип со знаком преобразуется в тип операнда без знака целочисленный тип....


§6.3.1.1p2 стандартного черновика C11 (n1570.pdf):

Если int может представлять все значения исходного типа (как ограниченные по ширине, для битового поля), значение преобразуется в int; в противном случае он преобразуется в unsigned int. Они называются целые рекламные акции .58) Все остальные типы не изменяются целым числом акции.

В вашем втором случае int не может представлять unsigned int k, потому что это вне диапазона. Оба операнда преобразуются в unsigned int и сравнивают равные.


Поскольку в продвижении без подписки нет расширений знака, результат будет дефрантным.

unsigned char k продвигается от unsigned char (value = 255) до int (value = 255).

В случае unsigned int k -1 продвигается от int (value = -1) до unsigned int (value = 2 ^ 32-1).


unsigned char k = -1;

-1 - целочисленный литерал типа int, который эквивалентен signed int. Когда вы назначаете большое знаковое целое число с меньшим неподписанным типом, результат будет усечен в undefined способами, стандарт C не гарантирует, что произойдет.

В реальном мире вне стандарта C это наиболее вероятно (предполагая 32-битный процессор, два дополнения):

-1 - 0xFFFFFFFF. Наименее значащий байт 0xFFFFFFFF будет присвоен k. k == 255. Попробуйте распечатать его с помощью printf("%u") и убедитесь сами.

В случае unsigned int k=-1 -1 все еще является подписанным int. Но он неявно (беззвучно) продвигается к unsigned int, когда он хранится в k. Когда вы позже сравните k == -1, правая сторона -1 снова будет повышена до неподписанного типа и сравняется с данными, хранящимися в k.

licensed under cc by-sa 3.0 with attribution.