Компилятор независимое выражение арифметические преобразования и целочисленные продвижения

Предположим, у нас есть присваивание с использованием переменных следующих типов:

uint64 = uint16 + uint16 + uint32 + uint64

Предположим, мы знаем, что результирующее значение r вписывается в uint64, если вся работа выполняется с использованием uint64.

Будет ли компилятор неявно продвигать два uint16 и uint32 в uint64 ДО выполнения каких-либо вычислений в соответствии со стандартными правилами C?

т.е.

1.) uint64 = uint16 + uint16 + uint32 + uint64

2.) uint64 = uint64 + uint64 + uint64 + uint64

В частности, применяя второе утверждение в следующем фрагменте:

Если оба операнда имеют одинаковый тип, дальнейшее преобразование не требуется.

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

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

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

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

Или же это правило применяется только к непосредственным значениям lhs и rhs арифметического выражения, так что добавление двух uint16 может быть сначала вычислено там, где типы не будут продвигаться до тех пор, пока не будет известен результат, а затем оно будет повышено до uint32, затем этот результат повышен до uint64 и т.д...

т.е.

1.) uint64 = uint16 + uint16 + uint32 + uint64

2.) uint64 = (((uint16 + uint16) + uint32) + uint64)

3.) uint64 = ((uint32 + uint32) + uint64)

4.) uint64 = (uint64 + uint64)

Пожалуйста, укажите мне на любые стандартные правила C, которые могут прояснить это для меня.

1 ответ

Решение

Правило применяется к промежуточному результату:

uint16 + uint16 + uint32 + uint64

эквивалентно

((uint16 + uint16) + uint32) + uint64

и обычные арифметические преобразования выполняются по обе стороны от + оператор.

(C99, 6.5.6 Аддитивные операторы p4) "Если оба операнда имеют арифметический тип, для них выполняются обычные арифметические преобразования".

Обратите внимание, что при условии 32-bitint, это на самом деле так же, как:

(uint64) ((unsigned int) ((int) uint16 + (int) uint16) + uint32) + uint64

uint16 повышен до int не для unsigned int, а затем результат преобразуется в unsigned int потому что uint32,

Другие вопросы по тегам