Читая книгу C ++ Primer 5th edition, я заметил, что signed char
со значением 256
не определено
Я решил попробовать это, и я увидел это std::cout
не работает для этой переменной char (Ничего не печатается).
Но на С тоже самое
signed char c = 256;
даст значение 0
для char c
,
Я пытался искать, но ничего не нашел.
Может кто-нибудь объяснить мне, почему это так в C ++?
Изменить: Я понимаю, что 256 это 2 байта, но почему то же самое, что в C, не происходит с C ++?
Изменить: см. Ответ Т.С. ниже. Лучше.
Целочисленное переполнение со знаком не определено в C ++ и C. В большинстве реализаций максимальное значение signed char
, SCHAR_MAX
, это 127, и поэтому вставка 256 в него переполнит его. Большую часть времени вы увидите, что число просто оборачивается (до 0), но это все еще неопределенное поведение.
Книга дико неверна. Там нет неопределенного поведения в
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
— оба операнда int
s, поэтому тип результата также int
, но значение находится вне диапазона представимых значений. Это правило здесь не применяется, так как единственное выражение 256
чей тип int
и 256, очевидно, находится в диапазоне представимых значений для int
,
Вы видите разницу между cout
а также printf
, Когда вы выводите символ с cout
вы не получаете числовое представление, вы получаете один символ. В этом случае персонаж был NUL
который не появляется на экране.
Смотрите пример на http://ideone.com/7n6Lqc
Чар вообще 8 bits
или byte
поэтому может держать 2^8
разные значения. Если это unsigned
, от 0
в 255
в противном случае, когда signed
от -128
в 127
unsigned char
значения (обычно педантичные) — от 0 до 255. Есть 256 значений, которые может содержать 1 байт.
Если вы получаете переполнение (обычно) значения используются по модулю 256, как и другие целочисленные типа по модулю MAX + 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);