這個問題類似于"是否所有指標都能保證正確地通過void *進行往返?",但稍微深入一點。
給定:
#include <stdint.h>
int i。
int *ip1 = &i;
void *vp1 = ip1;
intptr_t x = (intptr_t)vp1;
void *vp2 = (void *)x;
int *ip2 = vp2。
那么vp1 == vp2被保證是真的(即使他們可能不共享相同的二進制表示),但是ip1 == ip2被保證是真的嗎?也就是說,在這種情況下,平等關系是遞回的嗎?
uj5u.com熱心網友回復:
這種轉換是可以保證的。
首先,在C標準的6.3.2.3p1節中描述了從物件指標到void *和回傳的轉換:
其次,從指向
。void的指標可以轉換為任何物件型別的指標,或者從該指標中轉換。一個指向 任何物件型別的指標可以轉換為void的指標,然后再轉換回來;其結果應該是 與原始指標比較相等
void *到intptr_t再回傳的轉換在7.20.1.4p1節中描述:
下面的型別指定了一個有符號的整數型別,具有 屬性,任何有效的指向void的指標都可以被轉換為 這個型別,然后再轉換回void的指標,并且 結果將與原來的指標相比較:intptr_t下面的型別指定了一個無符號的整數型別,具有 屬性,任何有效的指向
void的指標都可以被轉換為 這個型別,然后再轉換回void的指標,并且 結果將與原來的指標相比較:uintptr_t這些型別是可選的。
在這種情況下,一個int *(ip1)被轉換成一個void *(vp1),而void *被轉換成一個intptr_t。
這個intptr_t被轉換回一個void * (vp2)。 根據7.20.1.4p1,vp2必須比較等于vp1。
然后vp2被轉換為int *(ip2)。 由于vp2與vp1相同,將vp2轉換為int *相當于將vp1轉換為int *,因此將產生一個指標,按照6.3.2.3p1的規定,比較等于ip1。
uj5u.com熱心網友回復:
對于指標的平等性,無論出處如何,都是由平等運算子的規范決定的。C 2018 6.5.9 6說:
兩個指標比較相等,當且僅當它們都是空指標,都是指向同一個物件(包括指向一個物件的指標和它開始的子物件)或函式的指標,都是指向同一個陣列物件最后一個元素的指標,或者一個是指向一個陣列物件結束后的指標,另一個是指向不同陣列物件開始的指標,而這個陣列物件恰好在地址空間里緊跟第一個陣列物件。
忽略空指標和指向函式的指標,這在這里不是一個問題,鑒于a == b和b == c評估為真,它們必須滿足規范中列出的條件之一,所以我們有這些情況:
給定a == b. |
給定b == c. |
a == c? |
|---|---|---|
a和b都指向同一個物件。
| b和c都指向同一個物件。
| a和c都指向同一個物件。因此a == c的評估結果為真。
|
a和b都指向同一個物件。
| c指向一個陣列物件的最后一個元素之后,b指向一個陣列物件的開始,剛好在它之后。
| c指向一個陣列物件的最后一個元素的過去,a指向一個陣列物件的開始,而這個陣列物件恰好在它之后。因此a == c的評估結果為真。
|
a和b都指向同一個陣列物件的最后一個元素之后。
| b和c都指向同一個陣列物件的最后一個元素的過去。
| a和c都指向同一個陣列物件的最后一個元素的過去。因此a == c的評估結果為真。
|
a指向一個陣列物件的最后一個元素的過去,b指向一個陣列物件的開始,在它之后。
| b和c都指向同一個物件。
| a指向一個陣列物件的最后一個元素之后,c指向一個陣列物件之后的開始。因此,a == c的評估結果為真。
|
b指向一個陣列物件的最后一個元素,a指向它后面的陣列物件的開始。
| b和c都指向一個陣列物件的最后一個元素的過去。
| c指向一個陣列物件的最后一個元素之后,a指向一個陣列物件的開始。因此,a == c的評估結果為真。
|
注意不存在b指向第一列中的一個物件和指向第二列中陣列最后一個元素的情況,或者反過來:無論這兩種指標是什么,在a == b和b == c中它必須是同一類。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/315423.html
標籤:
