簡體   English   中英

指向不同類型的指針可以有不同的二進制表示嗎?

[英]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 指針類型“指向cv T的指針”時,結果為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 指針轉換規則中。 你引用的段落隱含地將轉換的含義轉發到那里。

7.6.1.9 Static 演員表 [expr.static.cast]

“指向 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 指針類型“指向cv T的指針”時,結果為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 type T1 to the type “pointer to T2 ” (where T2 is an object type and the alignment requirements of T2 are no stricter than those of T1 ) 並返回其原始類型會產生原始指針值。 ——尾注]

第一句暗示我們可以將指針轉換為任意兩個 object 類型。 然而,(非規范性)注釋 7中的移情文本說 alignment 在這里也發揮了一些作用。 (這就是為什么我想出了上面那個int - long例子。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM