简体   繁体   中英

arbitrary value for enum variable

There is this code.

#include <iostream>
#include <climits>
enum e  {zero,one};
void main()
{
    e num=(e)INT_MAX;
    std::cout<<num;
}

Is it defined by the standart that output will be 2147483647?(on condition sizeof(int)=4 bytes)

No; when converting an integer to an enumeration, the enumeration value is only specified if the integer value is within range. From the standard:

7.2/10 An expression of arithmetic or enumeration type can be converted to an enumeration type explicitly. The value is unchanged if it is in the range of enumeration values of the enumeration type; otherwise the resulting enumeration value is unspecified.

where the "range" is described in a rather complicated manner in 7.2/7, and essentially goes up to the smallest value of 2^M-1 that's no less than the largest defined value.

The compiler is allowed to use any integer type to represent the enumeration, as long as it's large enough to hold all the enumeration values; so in this case, it's free to use a smaller type than int , such as char . Also, INT_MAX is only guaranteed to be at least 32767.

First, there's no guarantee that INT_MAX is 2147483647. Second, there's no guarantee that your enum will have an underlying type capable of storing 2147483647, nor of storing whatever value INT_MAX is.

Now, if you want to know if you can use values for which there is no enumerator defined, then the answer is "yes". You can use values without a corresponding enumerator, as long as the value fits in the range of the the enum. The maximum value in this range is the smallest 2^n - 1 which is greater than or equal to all of the enumerators. In your case, the range is [0,1], so no other values can be used in a well-defined manner.

In the following code, the enum range is [0,3], so 3 is a valid value, even if there's no enumerator for it.

#include <iostream>

enum e  {zero,one,two};
void main()
{
    e num=(e)3;
    std::cout<<num; // will print "3"
}

The smallest value in the range is 0 if there are no enumerators with negative values. If there are enumerators with negative values, it depends on the representation used by the implementation. If the implementation uses two's complement, it's -(max+1), otherwise it's just -max. Basically, if there are negative values, the range has one more bit :)

#include <iostream>

enum e  {minus_one=-1,zero,one,two};
void main()
{
    e num=(e)-3;
    std::cout<<num; // will print "-3"
}

And in C++11 you can specify the underlying type explicitly, if you want to make sure a value will be representable:

#include <iostream>
#include <cstdint>

enum e : std::int32_t {zero,one};
void main()
{
    e num=(e)2147483647;
    std::cout<<num; // will print "2147483647"
}

Can't find any direct explenation in C++ specs, but can be easily deduced. Underlying type of enum is compile-time defined. If compiler sees that enum e values easily fit in one byte it can decide to make it of type char .

That means you will not be able to store INT_MAX in this enum .

The range of valid enumeration values for an enumeration type is defined as follows in the C++ Working Draft, Section 7.2, paragraph 7:

For an enumeration whose underlying type is fixed, the values of the enumeration are the values of the underlying type. Otherwise, for an enumeration where emin is the smallest enumerator and emax is the largest, the values of the enumeration are the values in the range bmin to bmax, defined as follows: Let K be 1 for a two's complement representation and 0 for a one's complement or sign-magnitude representation. bmax is the smallest value greater than or equal to max(|emin| ? K, |emax|) and equal to 2^M ? 1, where M is a non-negative integer. bmin is zero if emin is non-negative and ?(bmax + K) otherwise. The size of the smallest bit-field large enough to hold all the values of the enumeration type is max(M, 1) if bmin is zero and M + 1 otherwise. It is possible to define an enumeration that has values not defined by any of its enumerators. If the enumerator-list is empty, the values of the enumeration are as if the enumeration had a single enumerator with value 0.

When converting an arithmetic or enumeration type to an enumeration type, the value is unchanged if it is in the range of enumeration values of the enumeration type. Otherwise, the value is unspecified.

To avoid unexpected behavior, the value being converted must be inside of the range of enumeration values. Furthermore, if it is necessary to check for out-of-range values dynamically, it must be done before the conversion.

No. 2147483647 is out of range for this enumeration.

Enumeration's range, if there are no negative enumerations, is 0 to 2^k - 1, where 2^k is smallest power of 2 for which all enumerations are in range. In this case, that would be 2^1. Therefore any value greater then 2 for e makes the output undefined.

The type of enum arg is integer.

enum e{zero, one} 

means

int zero = 0; int one =1;

if you assign INT_MAX to a integer type arg.

the result is 2^31

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM