Почему 256 для подписанного символа не определено в переполнении стека

Читая книгу C ++ Primer 5th edition, я заметил, что signed char со значением 256 не определено
Я решил попробовать это, и я увидел это std::cout не работает для этой переменной char (Ничего не печатается).

Но на С тоже самое
signed char c = 256;
даст значение 0 для char c,

Я пытался искать, но ничего не нашел.

Может кто-нибудь объяснить мне, почему это так в C ++?

Изменить: Я понимаю, что 256 это 2 байта, но почему то же самое, что в C, не происходит с C ++?

2

Решение

Изменить: см. Ответ Т.С. ниже. Лучше.

Целочисленное переполнение со знаком не определено в C ++ и C. В большинстве реализаций максимальное значение signed char, SCHAR_MAX, это 127, и поэтому вставка 256 в него переполнит его. Большую часть времени вы увидите, что число просто оборачивается (до 0), но это все еще неопределенное поведение.

6

Другие решения

Книга дико неверна. Там нет неопределенного поведения в

signed char c = 256;

256 целочисленный литерал типа int, Для инициализации signed char с его помощью он преобразуется в signed char (§8.5 [dcl.init] /17.8; все ссылки на N4140). Это преобразование регулируется §4.7 [conv.integral]:

1 Значение типа integer может быть преобразовано в значение типа
другой целочисленный тип. Значение типа перечисления с незаданной областью может быть
преобразуется в значение целого типа.

2 Если тип назначения не подписан, […]

3 Если тип назначения подписан, значение не изменяется, если оно может
быть представленным в типе назначения (и ширине битового поля);
в противном случае значение определяется реализацией.

Если signed char не может представлять 256, тогда преобразование дает определенное реализацией значение типа signed char, который затем используется для инициализации c, Здесь нет ничего неопределенного.


Когда люди говорят, что «переполнение со знаком — это UB», они обычно ссылаются на правило в §5 [expr] / p4:

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

Это делает UB выражения вроде INT_MAX + 1 — оба операнда ints, поэтому тип результата также int, но значение находится вне диапазона представимых значений. Это правило здесь не применяется, так как единственное выражение 256чей тип intи 256, очевидно, находится в диапазоне представимых значений для int,

10

Вы видите разницу между cout а также printf, Когда вы выводите символ с cout вы не получаете числовое представление, вы получаете один символ. В этом случае персонаж был NUL который не появляется на экране.

Смотрите пример на http://ideone.com/7n6Lqc

3

Чар вообще 8 bits или byteпоэтому может держать 2^8 разные значения. Если это unsigned, от 0 в 255 в противном случае, когда signed от -128 в 127

2

unsigned char значения (обычно педантичные) — от 0 до 255. Есть 256 значений, которые может содержать 1 байт.

Если вы получаете переполнение (обычно) значения используются по модулю 256, как и другие целочисленные типа по модулю MAX + 1

1

@Pubby Я не знаю, определяли ли стандарты C / C ++ поведение при переполнении целых чисел со знаком, но gcc, кажется, не всегда лечит (x < х + 1) как правда.
«<«оператор принимает подписанный int как операнд, поэтому
Икс < x + 1 -> (int) x < (int) x + (int) 1

следующий код производит вывод: 1 0 0 0 (32-битный Linux + gcc)

signed char c1, c2;
signed int i1, i2;

c1 = 127;
c2 = c1 + 1;

i1 = 2147483647;
i2 = i1 + 1;

printf("%d %d\n", c1 < c1 + 1, c1 < c2);
printf("%d %d\n", i1 < i1 + 1, i1 < i2);
0
По вопросам рекламы [email protected]