Pergunta

Encontrei isso no código em que estou trabalhando no momento e pensei que era a causa de alguns problemas que estou tendo.

Em um cabeçalho em algum lugar:

enum SpecificIndexes{
    //snip
    INVALID_INDEX = -1
};

Então mais tarde - inicialização:

nextIndex = INVALID_INDEX;

E use

if(nextIndex != INVALID_INDEX)
{
    //do stuff
}

Debugando o código, os valores no NextIndex não fizeram o sentido (eles eram muito grandes), e eu descobri que foi declarado:

unsigned int nextIndex;

Portanto, a configuração inicial para Invalid_index estava subindo o INT não assinado e definindo -o em um número enorme. Eu presumi que era isso que estava causando o problema, mas olhando mais de perto, o teste

if(nextIndex != INVALID_INDEX)

Estava se comportando corretamente, ou seja, nunca executou o corpo do IF quando o NextIndex era o "valor grande +ve".

Isso está correto? Como isso está acontecendo? O valor da enumeração está sendo implicitamente fundido para um INT não assinado do mesmo tipo que a variável e, portanto, sendo embrulhado da mesma maneira?

Foi útil?

Solução

Sim para tudo. É um código válido, também é comumente usado o código C ++ do lado da biblioteca, mais ainda no C ++ moderno (é estranho quando você o vê da primeira vez, mas é um padrão muito comum na realidade).

Em seguida, as enumes são assinadas INTs, mas elas são implicitamente lançadas em INTs não assinadas, agora isso, dependendo do seu compilador, pode dar um aviso, mas ainda é muito comumente usado, no entanto, você deve explicitamente esclarecer para os mantenedores.

Outras dicas

As enumes podem ser representadas por tipos integrais assinados ou não assinados, de acordo com se eles contêm valores negativos e como o compilador se sente. O exemplo aqui contém um valor negativo e, portanto, deve ser representado por um tipo integral assinado.

A comparação de igualdade entre tipos assinados e não assinados é segura e geralmente faz o que o autor pretendia - o valor assinado será convertido para não assinado primeiro, e o resultado de fazer isso é definido pelo padrão C ++ e é intuitivo (pelo menos, é quando você Conheça o tipo de destino. Exceto talvez se os números inteiros não forem o complemento de dois. Portanto, talvez não seja tão intuitivo, mas normalmente não causa problemas).

A comparação de pedidos tem mais probabilidade de resultar em erros. Por exemplo:

SpecificIndexes value = INVALID_VALUE;
return (value >= 0);

Retorna falsa, mas:

unsigned int value = INVALID_VALUE;
return (value >= 0);

retorna verdadeiro. Às vezes, o autor não apreciará a diferença, especialmente se o tipo de "valor" não for tão óbvio no ponto de uso. O compilador pode muito bem alertar sobre o segundo exemplo, porque (valor> = 0) é uma tautologia.

De fato, -1 é implicitamente fundido ao seu valor equivalente não assinado quando é atribuído ao NextValue. O equivalente não assinado é o valor com a mesma representação bit (que é 111111111111 ..., este é o valor máximo não assinado).

Mais tarde, na declaração de comparação, outro elenco implícito acontece.

Portanto, isso funciona agora, mas pode causar problemas no futuro. Nunca é uma boa ideia misturar valores assinados e não assinados.

Sim, acredito que as enumes são assinadas. Mudar

unsigned int nextIndex;

para

int nextIndex;

e seu programa deve funcionar.

O padrão C ++ permite que uma implementação use um tipo assinado para enums, mas não o requer. Portanto, você não pode, em geral, supor que é seguro colocar números negativos em uma enumeração.

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