Pergunta

Fiz alguns testes no VC++2010 misturando operandos de diferentes tamanhos que causam overflow na operação add:

int _tmain(int argc, _TCHAR* argv[])
{
    __int8 a=127;
    __int8 b=1;
    __int16 c=b+a;
    __int8  d=b+a;
    printf("c=%d,d=%d\n",c,d);

    return 0;
}

//result is: c=128, d=-128

Não entendo porque c==128!Meu entendimento é que em ambas as adições, b+a ainda são considerados adição de 2 assinados 8 bits variáveis.Portanto, o resultado é um estouro, ou seja,-128. Depois disso, o resultado é então promovido para int assinado de 16 bits para a primeira operação de atribuição e c ainda deve obter um valor -128 de 16 bits.Meu entendimento está correto?O padrão c++ é um pouco difícil de ler.O capítulo 4 parece falar sobre promoção inteira, mas não consigo encontrar nada relacionado a este exemplo específico.

Foi útil?

Solução

Meu entendimento é que em ambas as adições, b+a ainda são consideradas adição de 2 variáveis ​​assinadas de 8 bits.Portanto, o resultado é um estouro, ou seja,-128.

Não, a promoção acontece antes do + é avaliado, não depois dele.A adição acontece quando ambos a e b são positivos.Ambos os números são promovidos para ints para uma adição, adicionados como dois números positivos e depois convertidos em um número curto de 16 bits.Em nenhum momento do processo o resultado se torna negativo devido a um estouro, daí o resultado final de 128.

Indiscutivelmente, isso faz sentido:o comportamento de a e b corresponde ao de dois números em matemática, tornando-o mais intuitivo para os profissionais de línguas.

Outras dicas

É promoção integral.

1 Um pré-valor de um tipo inteiro diferente de bool, char16_t, char32_t ou wchar_t cuja classificação de conversão de inteiro (4.13) é menor que a classificação de int pode ser convertido em um pré-valor do tipo int se int puder representar todos os valores do tipo de origem ;caso contrário, o pré-valor de origem poderá ser convertido em um pré-valor do tipo unsigned int.[§ 4.5]

Nesta declaração

 __int16 c=b+a;

Primeiro, tudo char e short int valores são automaticamente elevados para int.Este processo é chamado promoção integral.A seguir, todos os operandos são convertidos até o tipo do maior operando, que é denominado digite promoção.[Herbert Schildt]

O valores de variáveis b e a será promovido a int e então a operação se aplica a eles.

Na representação inteira com complemento de dois, um valor com sinal é representado definindo o bit mais alto.Isso permite que a máquina adicione e subtraia números inteiros binários com as mesmas instruções, independentemente de o número inteiro estar assinado.

  a = 127 == 0x7F == 0b01111111
+ b =   1 == 0x01 == 0b00000001
-------------------------------
  c = 128 == 0x80 == 0b10000000
  d =-128 == 0x80 == 0b10000000

As variáveis c e d podem ter tipos diferentes, mas diferentes tipos de números inteiros são apenas interpretações diferentes de um único valor binário.Como você pode ver acima, o valor binário cabe perfeitamente em 8 bits.Como o padrão exige que os termos de uma expressão matemática sejam estendidos (promovidos) com zero ou sinal até o tamanho de uma palavra de máquina antes qualquer matemática é feita e nenhum operando será estendido por sinal, o resultado é sempre 0b10000000 não importa o tipo dos operandos.

Em resumo, a diferença entre os resultados é que, para um número inteiro de 16 bits, o bit de sinal é 0b1000000000000000 (qual a+b não tem), e para um número inteiro de 8 bits o bit de sinal é 0b10000000 (qual a+b tem).

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