2014-11-18 2 views
5

После прочтения вопроса 32 bit unsigned multiply on 64 bit causing undefined behavior? здесь, в StackOverflow, я начал задумываться над тем, могут ли типичные арифметические операции над малыми типами без знака привести к неопределенному поведению в соответствии со стандартом C99.Может ли генерация целых чисел без знака привести к неопределенному определенному поведению?

Например, возьмем следующий код:

#include <limits.h> 

... 

unsigned char x = UCHAR_MAX; 
unsigned char y = x + 1; 

Переменная x инициализируется до максимальной величины для данного типа unsigned char данных. Следующая строка - проблема: значение x + 1 больше, чем UCHAR_MAX и не может быть сохранено в переменной unsigned chary.

Я считаю, что на самом деле происходит следующее.

  • переменной x сначала повышен до типа данных int (раздел 6.3.1.1/2), то x + 1 оценивается как тип int данных.

Пусть есть реализация, где INT_MAX и UCHAR_MAX же - x + 1 приведет Целочисленное переполнение. Означает ли это, что приращение переменной x, несмотря на то, что это целочисленный тип без знака, может привести к неопределенному поведению из-за возможного переполнения целочисленного числа?

+0

Если 'sizeof (unsigned char) == sizeof (int)', применяется первый сценарий. – chux

+1

@chux Почему промотирование не происходит, если 'int' может представлять значение? –

+0

Я рассмотрю «6.3.1.8. Обычные арифметические преобразования». Это, кажется, сначала применимо »В противном случае, если операнд, имеющий беззнаковый целочисленный тип, имеет ранг, больший или равный рангам типа другого операнда, то операнд со знаком целочисленный тип преобразуется в тип операнда с целым типом без знака. " Это происходит до «В противном случае, если тип операнда со знаком целочисленного типа может представлять все значения типа операнда с типом unsigned integer type ...». – chux

ответ

5

По моему стандарту, реализация, которая использовала 15-разрядный char, могла законно хранить int в виде 15-разрядной величины и использовать второе 15-битовое слово для хранения знака вместе с 14 битами заполнения; в этом случае unsigned char будет содержать значения от 0 до 32 767, а int будет содержать значения от -32,767 до +32,767. Добавление 1 в (unsigned char)32767 действительно было бы неопределенным поведением. Аналогичная ситуация может возникнуть при любом большем размере char, если 32 767 было заменено на UCHAR_MAX.

Такая ситуация маловероятна, однако, по сравнению с реальными проблемами, связанными с целым числом без знака, упомянутым в другом сообщении.