鑄造一個指針只是躺在你的編譯器
void * ptr = malloc(sizeof(test));
((test *)ptr)->a = 5;
在第二行中,我們告訴編譯器「我知道我宣佈PTR爲(void *的),但我比你聰明,相信我,它實際上是一個(測試*)「。沒有什麼改變,ptr仍然只是一個指針,一個內存位置的地址,但編譯器假定它指向某個特定的東西。
check->a = 2; //this raises an error (dereferencing void pointer) when compiling
您必須投你想要的編譯器把它看作你從什麼宣稱它是不同的,每一次的變量。
一個更有趣的場景來解釋你可以用鑄造指針做什麼...
// struct with two ints, a and b
typedew struct testAB {
int a;
int b;
} testAB;
// struct with two ints, named in reverse order
typedef struct testBA {
int b;
int a;
} testBA;
int main(void) {
// construct a testAB struct
void *ptr = malloc(sizeof(testAB));
((testAB *)ptr)->a = 0
((testAB *)ptr)->b = 1
// treat ptr as a testBA struct
if (((testBA *)ptr)->a == 1) {
printf("this shouldn't happen, 'a' was set to 0");
}
}
,如果你運行上面的代碼,你會發現,printf語句將被執行。儘管我們將'a'設置爲0,if語句檢查a == 1.
這是因爲結構非常簡單。在上面的例子中,struct(s)只是兩個int,緊挨着彼此。就像兩個整數數組,像這樣:
int array[2] = {0, 1};
void *ptr = &array;
即使有這樣的表示,我們可以騙編譯器,我們可以強制編譯器把這個「陣」作爲我們的結構之一。
if (((testAB *)array)->a == 0)
printf("a is 0");
這是因爲,在引擎蓋下,編譯器將在一個struct命名變量剛剛從何處結構是offests。
// the following two lines have the same affect
((testAB *)array)->a = 0;
array[0] = 0;
// the following two lines have the same affect
((testAB *)array)->b = 2;
array[1] = 2;
如果我們告訴,這是一個(testAB *)編譯器,那麼 'A' 是指第一個int和 'B' 是指第二。如果我們告訴編譯器它是(testBA *),那麼'a'是第二個,'b'是第一個。
編譯代碼ALL變量名稱丟失。編譯器將結構分配減少到「將結構的第二個int設置爲2」。或者更具體地說,如果我們正在處理32位整數,則將結構的字節5,6,7和8設置爲0000 0000 0000 0010(二進制)(或者按相反的順序,如果我們編譯一點endian CPU)
你不能解除引用(即將運算符'*'或運算符' - >'應用於)void指針 –
你是否認爲'check =((test *)check);'檢查'? –
@MooingDuck爲什麼這不會改變檢查的類型? – Kumar