In C ++, should the size of the enum be equal to the size of its base type?

I often assume that the size of the enum matches the size of its base type. But is this consistent with the standard?

The standard (C ++ 14, n4296) says that each enumeration has a base type (7.2 / 5). The standard also states that objects are represented as sequences of bytes and that the size of an object is related to its representation:

3.9 / 4 The object representation of an object of type T is a sequence of N unsigned char objects occupied by an object of type T, where N is equal to SizeOf (T).

5.3.3 / 1 The sizeof operator gives the number of bytes in an object representing its operand.

However, I could not find any relationship between the base type of enum and the representation of the object. Whether there is a? If not, then I would say that the sizeof of an enum should not be the sizeof of its base type.

So my questions are:

  • Is there any relation between the base type of enum and its representation of the object?

  • Does the standard really require sizeof(std::underlying_type_t<E>) == sizeof(E) for any enum E?

+5
source share
2 answers

Adapted from: What is the C ++ Base Enumeration Type? , The older C ++ standard specified in 7.2 / 5:

The main type of enumeration is an integral type, which can represent all the counter values ​​defined in the enumeration. it is implementation-defined which integral type is used as the main type for the enumeration, except that the base type should not be greater than int if the value of the enumerator cannot int or unsigned int. If the list of enumerators is empty, the main type looks as if the enumeration had one enumerator with a value of 0. The value of sizeof () applied to the enumeration type is an object of the enumeration type or the enumerator is the value of the applied sizeof () to the base type.

From the nearest draft n4606 I could find 7.2 / 7 + 8, which reads:

7) For an enumeration whose base type is not fixed, the main type is an integral type that can represent all the counter values ​​defined in the enumeration. If the integral type cannot represent all the values ​​of the enumerator, the enumeration is poorly formed. it is implementation-defined which integral type is used as the main type, except that the base type should not be greater than int if the value of the enumerator cannot be placed in int or unsigned int. If the list of enumerations is empty, the base type looks as if the enumeration had a single enumerator with a value of 0.

8) For an enumeration whose base type is fixed, the enumeration values ​​are the values ​​of the base type. Otherwise, for an enumeration, where emin is the smallest counter and emax is the largest, enumeration values ​​are values ​​in the range from bmin to bmax, defined as follows: Let K - 1 for a two-component representation and 0 for a one addition or sign -value. bmax is the smallest value greater than or equal to max (| emin | - K, | emax |) and equal to 2M - 1, where M is a non-negative integer. bmin is zero if emin is non-negative and - (bmax + K) otherwise. The size is the smallest bit field large enough to hold all the values ​​of the enumeration type - 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 counters. If the enumeration list is empty, the enumeration value occurs as if the enumeration had one counter with a value of 0

On the one hand, this seems fairly close, on the other hand, the specific demand for the sizeof() operator has been removed. Nevertheless, I believe that it is safe enough to say that the answer to both questions is yes.

+1
source

I searched the standard and this is the best I could find (I know this may not be enough):

The base type is defined implicitly here (3.9.1 / 5 from C ++ 14):

The wchar_t type is a separate type whose values ​​can represent different codes for all members of the largest extended character set specified among supported locales (22.3.1). The type wchar_t must have the same (3.11), as one of the other integral types, called its base type . Types char16_t and char32_t denote different types with the same size, signature, and alignment as uint_least16_t and uint_least32_t, respectively, in <cstdint>, called basic types.

This definition refers to wchar_t , but I find it safe to say that it is a definition for the base type. (at least this is the best definition that the standard gives. In addition, the index of the C ++ 14 standard for the base type is indicated here)

It means:

  • performance should be the same

  • size should be equal

(But I think the base type should be better defined in the standard)

+1
source

Source: https://habr.com/ru/post/1273588/


All Articles