2010-09-01 84 views
1

我有一個函數可以創建一個指針數組。分配內存的函數通過傳遞給函數的參數返回新的內存指針。它可以重現該問題的最簡單的代碼如下:實際參數指針不匹配?

void foo (void** new_mem, size_t bytes) 
{ 
    *new_mem = malloc(bytes); 
} 

int main (void) 
{ 
    int** ptr_arr; // Want to create an array of pointers 

    foo(&ptr_arr, sizeof(int*)*100); // Create an array size of 100 
            // compiler emits warning: 
            // 'void **' differs in levels of indirection from 'int ***' 

    return 0; 
} 

我能投傳給foo的像這樣的第一個參數:但是「(無效**)& ptr_arr」擺脫的警告,我想知道:是否有更合適的解決方案?

回答

0

儘管從int *void *有保證的轉換,但從int **轉換爲void **並沒有這樣的保證。考慮這可能是爲什麼,請考慮int *實際上可能比void *小。因此,使用void **指針遍歷int *的數組會走錯誤的步幅並獲取錯誤的數據。此外,不能保證int *將使用與void *相同的表示形式,只是有一種方法可以在它們之間進行轉換。

在實踐中,我不知道任何機器哪裏會失敗。但這不是標準保證的。

編輯:eek,以及每個人都說通過int ***。但即使您通過int **,以上仍然適用。

編輯2:comp.lang.c常見問題有關於此的excellent discussion

+0

所以這聽起來像解決方案是使用一箇中間的'void *',它將包含新的內存地址,然後設置int **到中間void *。 – Andrew 2010-09-01 16:00:43

+0

@Andrew:不,使用中間的'void *'不會奇蹟般地使轉換有效。如果在'T *'和'U *'之間轉換無效,那麼'T *'將'void *'轉換爲'U *'也是無效的;但C不會提醒你。 – 2010-09-02 08:56:39

0

問題是你正在取得一個雙指針的地址並將它傳遞給一個雙指針參數。取一個值的地址創建一個指針,所以你最終得到一個三重指針int***,這就是爲什麼你會得到錯誤。

將結果投射到void**在技術上會在這裏工作,儘管它與類型系統上的濫用有關。

+0

將一個'int ***'投射到'void **'是在尋找麻煩。如果你對編譯器說謊,它會得到它的報復。 – 2010-09-01 15:43:45

+1

@Philip,它是C.即使你給它糖果,編譯器也會制定它的報復。 – JaredPar 2010-09-01 15:52:27

0

麻煩的是ptr_arr已經是一個int **, 當你做一個&ptr_arr,它會顯示爲int ***,你在做什麼這樣是不正確。

所以,你可以通過ptr_arr如果你的目的是要傳遞一個int **

另外,我覺得你的代碼可以與清理做得很好。你的方法似乎是錯誤的。

+0

除了'ptr_arr'不指向任何東西,'foo'指定給'* new_mem' – 2010-09-01 15:47:01

相關問題