[英]Class member function pointer - Pointers to members have different representations; cannot cast between them
[英]Can pointers to different types have different binary representations?
我想知道是否允許 C++ 實現以不同方式表示指向不同類型的指針。 例如,如果我們有 4 字節大小/對齊的int
和 8 字節大小/對齊long
,是否可以將指向int
/ long
的指針分別表示為右移 2/3 位的 object 地址? 這將有效地禁止將 pointer-to- long
轉換為 pointer-to- int
。
我問是因為[expr.reinterpret.cast/7] :
object 指針可以顯式轉換為不同類型的 object 指針。 當 object 指針類型的純右值
v
轉換為 object 指針類型“指向cvT
的指針”時,結果為static_cast<cv T*>(static_cast<cv void*>(v))
。[注7 :將指向
T1
類型的object的類型“指向T1
的指針”類型的指針轉換為“指向T2
的指針”類型(其中T2
是object類型,T2
的alignment要求並不比T1
的要求嚴格) 並返回其原始類型產生原始指針值。 ——尾注]
第一句話建議我們可以將指針轉換為任意兩個 object 類型。 然而,(非規范的)注釋 7中的同理心文本然后說 alignment 在這里也發揮了一些作用。 (這就是為什么我想出了上面那個int
- long
例子。)
作為具體示例,有一個 C++ 實現,其中指向單字節元素的指針大於指向多字節元素的指針,因為硬件使用字(而非字節)尋址。 為了模擬字節指針,C++ 使用了一個硬件指針加上一個額外的字節偏移量。
void*
存儲額外的偏移量,但int*
不存儲。 將int*
轉換為char*
是可行的(因為它必須符合標准),但是char*
到int*
會丟失該偏移量(您的注釋隱式允許)。
Cray T90 超級計算機就是此類硬件的一個例子。
我會看看我是否能找到標准論證,為什么這對於兼容的 C++ 編譯器來說是有效的; 我只知道有人這樣做了,但並不是說這樣做是合法的,而是暗示它是合法的。
這些規則將在 to-from void 指針轉換規則中。 你引用的段落隱含地將轉換的含義轉發到那里。
“指向 cv1 void 的指針”類型的純右值可以轉換為“指向 cv2 T 的指針”類型的純右值,其中 T 是 object 類型,並且 cv2 與 cv1 具有相同的 cv 資格,或者比 cv1 更高的 cv 資格。 如果原始指針值表示memory中某個字節的地址A,A不滿足T的alignment要求,則得到的指針值未指定。 否則,如果原始指針值指向 object a,並且有一個類型為 T(忽略 cv 限定)的 object b 可以與 a 進行指針互換,則結果是指向 b 的指針。 否則,指針值不會因轉換而改變。
這表明轉換為對齊程度更高的類型會生成一個未指定的指針,但轉換為實際上不存在的相等或更少對齊類型不會更改指針值。
允許從指向 4 字節對齊數據的指針轉換為指向 8 字節對齊數據的指針導致垃圾。
但是,每個 object 不相關的指針轉換都需要在邏輯上通過void*
進行往返。
object 指針可以顯式轉換為不同類型的 object 指針。 當 object 指針類型的純右值 v 轉換為 object 指針類型“指向 cv T 的指針”時,結果為
static_cast<cv T*>(static_cast<cv void*>(v))
。
(來自OP)
這涵蓋了void*
到T*
; 我還沒有找到T*
到void*
的轉換文本來使它成為一個完整的語言律師級別的答案。
答案是肯定的。 僅僅因為標准不禁止它,實現可以決定對指向不同類型的指針使用不同的表示,甚至對同一指針使用不同的可能表示。
由於大多數體系結構現在使用平面尋址(意味着指針的表示只是地址),因此沒有充分的理由這樣做。 但我仍然記得 8086 系統的舊段:偏移地址表示,它曾經允許 16 位系統處理 20 位地址(1024k)。 它使用 16 位段地址(移動 4 位以獲得真實地址),以及用於遠指針的 16 位偏移量,或用於近地址的僅 16 位(相對於當前段)。 在這種模式下,遠指針有一堆可能的表示。 順便說一句,在大型和緊湊模式 ( ref ) 中,遠尋址是默認設置(因此是由普通源產生的)。
我想知道是否允許 C++ 實現以不同方式表示指向不同類型的指針。 例如,如果我們有 4 字節大小/對齊的int
和 8 字節大小/對齊long
,是否可以將指針指向int
/ long
表示為 object 地址分別右移 2/3 位? 這將有效地禁止將指向long
的指針轉換為指向int
的指針。
我問是因為[expr.reinterpret.cast/7] :
object 指針可以顯式轉換為不同類型的 object 指針。 當 object 指針類型的純右值
v
轉換為 object 指針類型“指向cvT
的指針”時,結果為static_cast<cv T*>(static_cast<cv void*>(v))
。[ Note 7 : Converting a pointer of type “pointer to
T1
” that points to an object of typeT1
to the type “pointer toT2
” (whereT2
is an object type and the alignment requirements ofT2
are no stricter than those ofT1
) 並返回其原始類型會產生原始指針值。 ——尾注]
第一句暗示我們可以將指針轉換為任意兩個 object 類型。 然而,(非規范性)注釋 7中的移情文本說 alignment 在這里也發揮了一些作用。 (這就是為什么我想出了上面那個int
- long
例子。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.