2017-08-14 69 views
4

从一些C遗留代码我得到一些常数为int *。在C++部分中,我有一个底层类型为int的枚举。在单个值基础上的枚举和int之间的转换工作。但是,int *enum *之间的转换是不可能的。看下面的代码示例。如何转换int *和枚举*?

为什么会这样以及如何将指针转换为一些int值指向int枚举,反之亦然?我有点期待它的工作,因为单值转换的工作和基础类型是相同的。我阅读了大约What happens if you static_cast invalid value to enum class? ,但无法确定潜在无效值是否在此发挥作用。

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; 
+0

你试过'reinterpret_cast'吗? – VTT

+0

虽然您可以使用'reinterpret_cast'进行转换,但这样做很少有用。不能调用未定义的行为来解引用生成的指针。 – davmac

+0

@davmac好像我应该确保我关闭严格的别名规则或开始考虑复制。感谢答案和下面的讨论,我现在更好地理解答案。 – Trilarion

回答

3

这是为什么?

但从int*编译点和E*是不同的非相关类型的指针,这就是为什么static_cast在这里不适用。

我该如何将一个int指针转换为int枚举指针,反之亦然?

可能尝试reinterpret_cast代替static_cast

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

reinterpret_cast

任何指针类型T1的到对象可被转换为指针到另一种类型的CV的对象T2

但是,请注意,那个dereferenci ng fj(即,与*f*j)将是违规的严格别名规则(更多细节参见下面的讨论)。这意味着这种转换虽然是严格可行的,但通常没有用处。

+3

值得注意的是,虽然这个“有效”,但它很可能是严格的别名违规。 – Frank

+0

我同意reinterpret_cast解决了这个问题。不过,我想知道为什么int *和E *不同,而int和E不是。无论如何,将标志解决。 – Trilarion

+0

@Trilarion在某些情况下,如果使用'static_cast'是合法的,则明确列出它们。从形式上讲,你的案件不属于任何这些案件,所以......你必须改用'reinterpret_cast'。 –

0

枚举的默认“基本类型”是int,并且可以在OP中明确指定。从逻辑上讲,存储在E* e处的值是其中E是枚举类型为int的枚举是int。它不能静态投射。

有C中没有保证++中基本类型的enum(说)是布局short兼容,但即使语言收紧,这一点有可能是类型兼容的问题/

一个问题是,E*int*pi会违反类型安全性,因为可以使用pi来静默设置枚举范围外的值。 类似地,如果整数值不在枚举中,则int*E*可能违反类型安全性。然而

注意标准作出明确记有什么可以阻止枚举取一个值的定义设定值之外:

这组值是用来定义推广和转化的语义枚举类型。它并不排除枚举类型的表达式具有超出此范围的值。

在这里看到:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf(见注95底部的P 156)

可能(如果布局兼容性得到保证)是有效的唯一情况是E*const int*因为E*所有值都int s,并且通过int *指针无法(正确)修改该值,而不会进一步违反类型系统。

但我认为语言的定义并不是那么微妙。

+0

“逻辑上,存储在E * e中的值,其中E是基类型为int的枚举,是一个int。”(我想)我知道你的意思,我认为这样说可能会引起误解。没有正式的保证,表示枚举符合其基本类型(或者我没有意识到,没有详尽地检查tbh)。另外:“pi可以用来在枚举之外静静地设置值” - 通过'int *'这样做也会违反严格的别名规则。 – davmac

+0

没有声明枚举与其“基本类型”或“基础类型”(AFAIK)“布局兼容”。我正在完善这个陈述。我建议这里的标准是不必要的限制。特别考虑到注释'这组值用于定义枚举类型的提升和转换语义。它并不排除枚举类型的表达式具有超出此范围的值。'。从我可以看到的一个实现可以使用'int'甚至对于基类型为“short”的枚举。 – Persixty