Переменное продвижение по C

У меня возникли проблемы с выяснением, почему в каждом из этих случаев вывод отличается. В образце Code a есть переменная продвижение по мере того, как я ожидаю, и результат > 6, но в примере кода b результат <= 6:

/* **Code a** */
puts("Code a\n");
unsigned int a = 6;
int b = -20;
( a+b > 6) ? puts("> 6\n") : puts("<= 6\n");

/* **Code b** */
puts("Code b:\n");
uint8_t a1 = 6;
int8_t  b1 = -20;  
( a1+b1 > 6) ? puts("> 6\n") : puts("<= 6\n");

Вывод:

Code a

> 6

Code b:

<= 6

Ответы

Ответ 1

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

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

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

Для справки проект стандарта C11 в разделе 6.5.6 Аддитивные операторы говорят:

Если оба операнда имеют арифметический тип, обычные арифметические преобразования выполняются на их.

section 6.3.1.8 Обычные арифметические преобразования говорят:

Многие операторы, ожидающие операндов арифметического типа, конверсий и типов результатов результатов аналогичным образом. Цель - определить общий реальный тип для операндов и результата. Для заданные операнды, каждый операнд преобразуется без изменения типа домен, к типу, соответствующий реальный тип которого является общим реальным тип. Если явно не указано иное, общий реальный тип также соответствующий реальный тип результата, домен типа которого является тип домена операндов, если они одинаковы, и сложный в противном случае. Этот шаблон называется обычным арифметическим преобразованием

[...]

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

[...]

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

[...]

Хорошую ссылку для обоснования для этого можно найти в вопросе: Почему короткое преобразование в int перед арифметическими операциями в C и С++?.