2017-08-14 111 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