C ++ enum to unsigned int comparison

I found this in the code I am currently working on and thought that this was the cause of some of the problems that I ran into.

In the header somewhere:

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

      

Then later - initialization:

nextIndex = INVALID_INDEX;

      

and use

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

      

Debugging the code, the values ​​in nextIndex don't quite make sense (they were very large) and I found that it was declared:

unsigned int nextIndex;

      

So the initial setting to INVALID_INDEX was insufficient for an unsigned integer and set it to a huge number. I assumed this was the cause of the problem, but if you look closely, the test

if(nextIndex != INVALID_INDEX)

      

Worked correctly, meaning it never executed the if body when nextIndex was "high + ve".

It is right? How does this happen? Is the enum value implicitly cast to an unsigned int of the same type as the variable, and therefore wrapped in the same way?

+1


source to share


5 answers


Yes to everything. This is valid code, it is also widely used on the C ++ library side, even more so in modern C ++ (it's weird the first time you see it, but its a very general pattern in reality).



The enums are then signed with ints, but they are implicitly translated into unsigned ints, now it depends on your compiler, may give a warning, but it is still very commonly used, however you have to explicitly make it clear to maintainers.

+11


source


enums can be signed or unsigned integer types depending on whether they contain any negative values ​​and what the compiler is. The example here contains a negative value and therefore must be represented by a signed integral type.

Equality comparison between signed and unsigned types is safe and usually does what the author intended - the signed value will first be converted to unsigned, and the result of doing this is defined by the C ++ standard and is intuitive (at least when you know the target type, the exception, perhaps, is if the integers are not two's complement, so it may not be intuitive, but usually not a problem).

Comparing orders is likely to lead to errors. For example:

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

      



returns false, but:

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

      

returns true. Sometimes the author will not appreciate the difference, especially if the type "value" is not entirely obvious at the point of use. The compiler can be good at warning about the second example, though, since (value> = 0) is a tautology.

+2


source


In fact, -1 is implicitly cast to its unsigned equivalent when it is assigned to nextValue. An unsigned designator is a value with the same bitwise representation (which is 111111111111 ..., which is the maximum unsigned value).

Further implicit casting occurs in the comparison instruction.

So this is working right now, but may cause problems in the future. Sign and unsigned values ​​cannot be mixed.

+1


source


Yes, I believe the transfers are signed. Edit

unsigned int nextIndex;

      

to

int nextIndex;

      

and your program should work.

0


source


The C ++ standard allows implementations to use a signed type for enumerations, but does not require one. Therefore, you cannot generally assume that it is safe to put negative numbers in an enum.

0


source







All Articles