简体   繁体   中英

How to convert between int * and enum *?

From some C legacy code I get a number of constants as int * . In the C++ part, I have an enum of underlying type int. Conversion between the enum and int on a single value basis works. However, conversion between int * and enum * is not possible. See code example below.

Why is that and how would I convert a pointer to some int values to a pointer to int enums and vice versa? I kind of expect it to work since the single value conversions work and the underlying types are the same. I read about What happens if you static_cast invalid value to enum class? but could not determine if potentially invalid values play a role here.

int i = 3;
enum E : int;
E e;

e = static_cast<E>(i);   // ok
i = static_cast<int>(e); // ok

int *j;
E * f;

j = static_cast<int *>(&i); // ok
f = static_cast<E *>(&i);   // 'static_cast': cannot convert from 'int *' to 'E *'
j = static_cast<int *>(&e); // 'static_cast': cannot convert from 'E *' to 'int *'

// now use j and f
*j = *f;

Why is that?

From the compiler point of view int* and E* are pointers of different non-related types, that is why static_cast is not applicable here.

How would I convert a pointer to some int values to a pointer to int enums and vice versa?

You might try reinterpret_cast instead of static_cast :

f = reinterpret_cast<E *>(&i);
j = reinterpret_cast<int *>(&e);

From reinterpret_cast :

Any pointer to object of type T1 can be converted to pointer to object of another type cv T2

However, note, that dereferencing f or j (ie with *f or *j ) will be a violation of the strict aliasing rule (for more details see the discussion below). This means that this kind of conversion, though strictly possible, is usually not useful.

The default 'base type' of an enum is int and can be explicitly specified in the OP. Logically the value stored at E* e where E is an enumeration with base type int is an int . It can't be statically cast.

There's no guarantee in C++ that an enum of base type (say) is layout compatible with short but even if the language tightened up that point there could be issues of type compatibility/

One issue is that E* to int*pi would violate type-safety because pi could be used to quietly set values outside the enumeration. Similarly int* to E* may violate type safety if the integer value isn't in the enumeration.

Note however the standard makes a clear note that there's nothing to preclude an enum taking a value outside its defined set of values:

This set of values is used to define promotion and conversion semantics for the enumeration type. It does not preclude an expression of enumeration type from having a value that falls outside this range.

See here: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf (see note 95 bottom of p. 156)

The only case that could (if layout-compatibility were assured) be valid is E* to const int* because all values of E* are int s and the value cannot be (correctly) modified through the int * pointer without a further violation of the type system.

But I think the language definition is not that subtle.

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