2017-09-05 49 views
-5

我正在測試我在將void指針投射到同一變量中的不同類型時遇到的問題。這個問題似乎是在對鑄造的指針使用相同的變量時。下面我有一段代碼來測試這個。有人能夠告訴我爲什麼該程序無法編譯爲這種情況?在相同變量中投射void指針會導致編譯錯誤

#include <stdlib.h> 

typedef struct test { 

    int a; 

}test; 

int main() { 

    void * check; 
    test * check2; 
    check = malloc(sizeof(test)); 

    check = ((test *) check); 
    check2 = (test *)check; 


    check->a = 2; //this raises an error (dereferencing void pointer) when compiling 
    check2->a = 2; //this works 
    ((test *)check)->a = 2; //this also works 
} 
+2

你不能解除引用(即將運算符'*'或運算符' - >'應用於)void指針 –

+2

你是否認爲'check =((test *)check);'檢查'? –

+0

@MooingDuck爲什麼這不會改變檢查的類型? – Kumar

回答

0

鑄造一個指針只是躺在你的編譯器

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)

相關問題