Pergunta

Se eu executar o seguinte código em C:

#include <stdint.h>

uint16_t a = 4000;
uint16_t b = 8000;

int32_t c = a - b;

printf("%d", c);

Ela imprime corretamente '-4000' como resultado. No entanto, estou um pouco confuso: não deve haver um estouro aritmético quando subtraindo um inteiro sem sinal maior do outro? Que regras de fundição estão em jogo aqui? Esta questão parece um noobish pouco, então qualquer referência seria muito apreciada.

Foi útil?

Solução

A questão é realmente um pouco complicado. Operandos de expressões aritméticas são convertidos utilizando regras específicas que você pode ver na Seção 3.2.1.5 do padrão (C89) . No seu caso, a resposta depende do que o tipo uint16_t é. Se for menor do que int, short int digamos, em seguida, os operandos são convertidos para int e você começa -4000, mas em um sistema de 16 bits, uint16_t poderia ser unsigned int e conversão para um tipo assinado não aconteceria automaticamente.

Outras dicas

A resposta curta é que estes são todos promovidos a int durante a subtração. Para a longa resposta, olhar na seção 6.3.1.1 do padrão C, onde ele fala sobre inteiros promoções em expressões aritméticas. idioma relevante do padrão:

Se um int pode representar todos os valores de o tipo de original, o valor é convertido para um int ; caso contrário, é convertido para um unsigned int . Estes são chamados de promoções inteiros . Todos os outros tipos são inalterados pela promoções inteiros.

Os detalhes estão lá também, mas eles ficam bastante desagradável.

Ambos os operandos são promovidos a int32_t durante a subtração. Se o resultado tinha sido maior do que o valor máximo para int32_t você teria visto estouro.

Há, de fato, um estouro, mas C não lhe diz.

O estouro deixa um valor que passa a ser -4000 quando interpretado como um inteiro assinado. Isso funciona como projetado em máquinas complemento de 2.

Tente interpretar o resultado como não assinado, e você vai perceber que (u1-u2) avalia para um número aparentemente não relacionados quando u1

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top