[英]Why do I Have to reinterpret_cast Pointer Pointers?
所以這個static_cast
代碼是完全合法的:
int n = 13;
void* pn = static_cast<void*>(&n);
void** ppn = &pn;
然而,必須將其轉換為reinterpret_cast
以進行編譯:
int n = 13;
int* foo = &n;
void** bar = static_cast<void**>(&foo);
如果我不改變它我得到錯誤:
錯誤C2440:
static_cast
:無法從int **
轉換為void **
注意:指向的類型不相關; 轉換需要reinterpret_cast
,C風格的轉換或函數式轉換
所以我認為問題是“類型無關”。 然而我仍然不明白,如果從int*
到void*
是可以的void*
它們如何作為int**
和void**
無關?
int
與void
無關。 對於int**
和void**
也是如此,因此無法使用static_cast
進行轉換。
void*
但是,很特別 。 任何數據指針類型(包括int*
)都可以是static_cast
到void*
和back,盡管沒有類型與void
相關(更進一步,轉換為void*
不需要static_cast
轉換,因為它是隱式的)。 int*
沒有這個屬性,也沒有void**
,也沒有除void*
之外的任何其他指針。
已授予void*
的額外自由帶有額外限制。 void*
不能被指向,也不能與指針算法一起使用。 這些限制是唯一可能的,因為永遠不會有void
類型的對象。 或者從相反的觀點來看,由於這些限制, void
對象不可能存在。
void**
不能給予這些自由,因為它不能給予同樣的限制。 它不能被賦予這些限制,因為void*
對象確實存在並且它們需要存在。 如果我們不能間接或迭代void**
,那么我們就不能使用void*
數組。
void* pn = static_cast<void*>(&n);
是一種隱含的轉換; 你也可以寫
void *pn = &n;
這意味着pn
存儲指向某個對象類型的指針; 程序員負責知道該對象類型是什么。 要回送你需要一個static_cast
:
int *pi = static_cast<int*>(pn);
請注意,使用static_cast
轉換為與原始明顯不同的任何類型( float
明顯不同, const int
不是)是一種重新解釋的方法。 您應該拼寫reinterpret_cast
不是隱式轉換(或static_cast
),后跟static_cast
。
這是void*
一個完整目的,一個追溯到C的概念,其中強制轉換拼寫為C風格的強制轉換(不是static_cast
......),但具有相同的含義。
回到C和C ++中的聲明語法:
指向int
的指針是int (*pi);
(括號沒用,但有助於說明這一點),你可以這樣讀:我聲明表達式(*pi)
類型為int
。 您可以通過以下方式讀取函數聲明:in int f(int i);
我聲明如果i
有int
類型,那么f(i)
類型為int
。
聲明void (*pi);
看起來像是指向void
的指針,但是沒有類型為void
的對象,表達式*pi
甚至沒有很好地形成,它沒有意義。 這是類型系統中的一個特例 :語法表示“指向void的指針”,語義表示“指向某事物的指針”。
在C和C ++中,指針對象是第一個類對象,您可以獲取其地址並指向指針等。(與Java對比,其中像其他基本類型的引用不是類對象。)
所以你可以有一個int**
, int***
...指向(指針...到int
); 你可以出於同樣的原因void**
:聲明為指向(指向void的指針),語義指向(指向某事物的指針)。
就像指向int
的指針一樣,無法在沒有強制轉換的情況下指向float
的指針:
float *f = &i; // ill-formed
由於類型不匹配,與void**
不同的類型不能分配給void**
: 取消引用void**
的結果必須是void*
對象 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.