Por que os tipos inteiros são promovidos durante a adição em C?

Então, tivemos um problema de campo e, após dias de depuração, reduzimos o problema a esse bit específico de código, onde o processamento em um loop while não estava acontecendo:

// heavily redacted code
// numberA and numberB are both of uint16_t
// Important stuff happens in that while loop

while ( numberA + 1 == numberB )
{
    // some processing
}

Isso funcionou bem, até atingirmos o limite uint16 de 65535. Outro monte de instruções impressas posteriormente, descobrimos quenumberA + 1 teve um valor de65536, enquantonumberB embrulhado de volta para0. Isso falhou na verificação e nenhum processamento foi concluído.

Isso me deixou curioso, então montei um programa C rápido (compilado com o GCC 4.9.2) para verificar isso:

#include <stdio.h>
#include <stdint.h>

int main()
{

    uint16_t numberA, numberB;
    numberA = 65535;
    numberB = numberA + 1;

    uint32_t numberC, numberD;
    numberC = 4294967295;
    numberD = numberC + 1;

    printf("numberA = %d\n", numberA + 1);
    printf("numberB = %d\n", numberB);

    printf("numberC = %d\n", numberC + 1);
    printf("numberD = %d\n", numberD);

    return 0;
}

E o resultado foi:

numberA = 65536
numberB = 0
numberC = 0
numberD = 0

Portanto, parece que o resultado denumberA + 1 foi promovido para uint32_t. Isso é pretendido pela linguagem C? Ou isso é uma raridade do compilador / hardware?

questionAnswers(4)

yourAnswerToTheQuestion