Поведение оператора приращения на границах символьного типа

Интересно, как C++ ведет себя в этом случае:

char variable = 127;
variable++;

В этом случае переменная теперь равна -128. Однако оператор приращения обернул значение до его нижней границы или произошло переполнение?


person Momhain    schedule 26.01.2012    source источник


Ответы (2)


Произошло переполнение, что привело к неопределенному поведению.

Раздел 5.5:

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

Далее в стандарте отмечается, что целочисленные переполнения в большинстве реализаций игнорируются. Но это не является гарантией.

person Luchian Grigore    schedule 26.01.2012

Обычный char может быть как подписанным, так и беззнаковым. Если максимальное значение равно 127, то оно должно быть подписано в вашей реализации.

Для беззнаковых типов "переполнение" четко определено и вызывает зацикливание. Для подписанных типов поведение при арифметическом переполнении не определено (обходной цикл типичен, но не обязателен). Но на самом деле это не применимо в данном конкретном случае; вместо этого значение, хранящееся в variable, определяется реализацией.

Для типов уже, чем int, все немного сложнее. Этот:

variable ++;

эквивалентно этому:

variable = variable + 1;

К операндам оператора + применяются «обычные арифметические преобразования», что в данном случае означает, что оба операнда повышаются до int. Поскольку int более чем достаточно широк, чтобы вместить результат, переполнения нет; результат 128 и имеет тип int. Когда этот результат сохраняется обратно в variable, он преобразуется из int в char.

Правила переполнения для преобразований отличаются от правил для арифметических операций, таких как «+». Для преобразования подписанного в подписанное или неподписанного в подписанное, если значение не может быть представлено в целевом типе, поведение не является неопределенным; он просто дает результат, определяемый реализацией.

Для типичной реализации, которая использует представление с дополнением до 2 для целых типов со знаком, сохраненное значение, вероятно, будет -128, но возможны и другие варианты поведения. (Например, реализация может использовать арифметику насыщения.)

Другая (довольно неясная) возможность заключается в том, что char и int могут иметь одинаковый размер (что может произойти, только если char составляет не менее 16 бит). Это может иметь некоторые интересные эффекты, но я не буду вдаваться в подробности (пока).

person Keith Thompson    schedule 26.01.2012
comment
Означает ли это, что unsigned char может быть того же типа, что и char? То же самое относится и к другим интегральным типам? - person xtofl; 26.01.2012
comment
@xtofl: Нет, char, signed char и unsigned char всегда являются разными типами, но char имеет то же представление, что и один из них. Точно так же int и long — это разные типы, которые могут иметь или не иметь одинаковое представление и так далее. - person Keith Thompson; 26.01.2012