Pergunta

Eu li um pouco C spec que não assinados variáveis(em particular unsigned short int) realizar alguns assim chamados o envoltório em torno de no estouro de número inteiro, apesar de eu não poderia encontrar qualquer coisa sobre assinado variáveis, exceto que eu saí com comportamento indefinido.

O meu professor disse-me que os seus valores também obter enrolado (talvez ele apenas quis dizer gcc).Eu pensei que os bits apenas ficar truncado e os bits saí com me dar algum estranho valor!

O que envoltório em torno do que é e como é diferente de apenas truncar bits.

Foi útil?

Solução

Inteiro de variáveis não possuem envoltório comportamento em linguagem C.Assinado de estouro de número inteiro durante cálculos aritméticos produz comportamento indefinido.Nota BTW que o compilador GCC que você mencionou é conhecido pela aplicação de estrito sobrecarga semântica em otimizações, o que significa que ele aproveita a liberdade proporcionada por tal comportamento indefinido situações:GCC compilador assume que o número inteiro assinado de valores nunca enrole ao redor.O que significa que o GCC, na verdade, passa a ser um dos compiladores em que você não dependem de wrap-around comportamento do inteiro assinado de tipos.

Por exemplo, o compilador GCC pode-se assumir que para a variável int i a seguinte condição

if (i > 0 && i + 1 > 0)

é equivalente a um mero

if (i > 0)

Isso é exatamente o que estrito sobrecarga semântica significa.

Inteiro não assinado tipos de implementar módulo aritmético.O módulo é igual 2^N onde N é o número de bits na representação de valor do tipo.Por esta razão inteiro não assinado de tipos, de fato, aparecer para moldar em excesso.

No entanto, a linguagem C nunca realiza cálculos aritméticos em domínios menores do que a da int/unsigned int.Tipo unsigned short int que você menciona na sua pergunta, normalmente será promovido para o tipo de int em expressões antes de qualquer cálculos começar (supondo que o intervalo de unsigned short encaixa-se no intervalo de int).O que significa que 1) os cálculos com unsigned short int será efectuada no domínio da int, com o estouro acontecer quando int estouros, 2) excesso durante tais cálculos levarão a um comportamento indefinido, não wrap-around comportamento.

Por exemplo, este código produz um envoltório em torno de

unsigned i = USHRT_MAX;
i *= INT_MAX; /* <- unsigned arithmetic, overflows, wraps around */

enquanto esse código

unsigned short i = USHRT_MAX;
i *= INT_MAX; /* <- signed arithmetic, overflows, produces undefined behavior */

leva a um comportamento indefinido.

Se não int estouro acontece e o resultado é convertido para um unsigned short int tipo, ele é novamente reduzida por módulo 2^N, que irá aparecer como se o valor foi enrolado.

Outras dicas

Imagine que você tem um tipo de dados de que apenas 3 bits de largura.Isso permite que você para representar a 8 valores distintos, de 0 a 7.Se você adicionar 1 a 7, você vai "wrap around" de volta para 0, porque você não tem o suficiente bits para representar o valor de 8 (1000).

Este comportamento é bem definidos para não assinados tipos.É não bem-definidos para assinada tipos, porque existem vários métodos para representação de valores assinados, e o resultado de um estouro vai ser interpretados de maneira diferente com base nesse método.

Sinal-magnitude:os primeiros bits representa o sinal;0 para positivo e 1 para negativo.Se o meu tipo é de três bits de largura de novo, então eu posso representar assinado valores da seguinte maneira:

000  =  0
001  =  1
010  =  2
011  =  3
100  = -0
101  = -1
110  = -2
111  = -3

Uma vez que um bit é levado para o sinal, eu só tenho dois bits para codificar um valor de 0 a 3.Se eu adicionar de 1 a 3, eu vou transbordar com -0 como o resultado.Sim, existem duas representações para 0, um positivo e um negativo.Você não encontrará sinal-magnitude representação de tudo o que, muitas vezes.

Um complemento:o valor negativo é o bit a bit-o inverso do que o valor positivo.Novamente, usando os três bits tipo:

000  =  0
001  =  1
010  =  2
011  =  3
100  = -3
101  = -2
110  = -1 
111  = -0

Eu tenho três bits para codificar os meus valores, mas o intervalo é [-3, 3].Se eu adicionar de 1 a 3, eu vou transbordar com -3 como o resultado.Isso é diferente do sinal-magnitude resultado acima.Novamente, há duas codificações para 0 usando este método.

Em complemento de dois:o valor negativo é o bit a bit o inverso do que o valor positivo, mais 1.Nos três bits do sistema:

000  =  0
001  =  1
010  =  2
011  =  3
100  = -4
101  = -3
110  = -2
111  = -1

Se eu adicionar de 1 a 3, eu vou transbordar com -4 como um resultado, que é diferente dos dois métodos anteriores.Note que temos um pouco maior intervalo de valores [-4, 3] e apenas uma representação para 0.

Complemento de dois é, provavelmente, o método mais comum de representação de valores assinados, mas não é a única, portanto o C padrão não pode fazer quaisquer garantias de que vai acontecer quando você estouro de um inteiro assinado de tipo.De modo que deixa o comportamento não definido assim, o compilador não tem que lidar com a interpretação de representações múltiplas.

O comportamento indefinido vem a partir do início de questões de portabilidade quando assinado tipos de número inteiro pode ser representado como sinal de & magnitude, complemento ou de complemento de dois.

Atualmente, as arquiteturas de representar números inteiros como complemento de dois que fazer envoltório em torno.Mas cuidado :desde o seu compilador é certo assumir que você não será executado comportamento indefinido, você pode encontrar estranho de bugs, quando a otimização é sobre.

Em uma assinado inteiro de 8 bits, a definição intuitiva de envoltório em torno do que pode parecer como ir de +127 para -128-em complemento de dois binários:0111111 (127) e 1000000 (-128).Como você pode ver, que é o progresso natural de incrementar o binário de dados--sem considerar a ele para representar um número inteiro, assinado ou não assinado.Contador intuitivamente, o real overflow ocorre quando o movimento de -1 (11111111) para 0 (00000000) o número inteiro não assinado o sentido de wrap-around.

Este não responder a mais profunda questão do que é o comportamento correto quando um número inteiro assinado excede porque não há "corrigir" o comportamento, de acordo com o padrão.

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