2010-08-17 87 views
7

我有以下程序。但是,我不明白爲什麼我必須傳遞數組的地址。當他們都指向同一個地址時。這是int數組的第一個元素的地址。爲什麼我不能直接在C中將指針分配給指針?

我得到一個警告,當我嘗試做這個 「不兼容的指針類型賦值」:

ptr = var; 

完整的源代碼:

void print_values(int (*ptr)[5]) 
{ 
    size_t i = 0; 
    for(i = 0; i < 5; i++) { 
     printf("%d: [ %d ]\n", i, (*ptr)[i]); 
    } 
} 

int main(void) 
{ 
    /* declare a pointer to an array integers */ 
    int (*ptr)[5] = NULL; 
    /* array of integers */ 
    int var[] = {1, 2, 3, 4, 5}; 
    /* assign the address of where the array is pointing to (first element) */ 
    ptr = &var; 
    /* Both are pointing to the exact same address */ 
    printf("var [ %p ]\n",(void*)var); 
    printf("&var [ %p ]\n", (void*)&var); 

    print_values(ptr); 
    return 0; 
} 

我編譯gcc 4.4.4 c89 -Wall -Wextra -O0

+0

我試圖重寫你的標題,因爲它沒有意義。請確認我是否正確選擇了問題的要點。 – 2010-08-17 16:40:09

+0

我覺得你的標題聽起來比我的好。謝謝。 – ant2009 2010-08-18 02:06:52

+0

你的代碼片段編譯得很好。你的意思是如果你將'ptr = var'添加到main中,你會得到一個錯誤? – 2015-07-21 14:56:58

回答

17

這純屬類型問題。

在大多數表達式上下文中,數組的名稱(例如var)衰減爲指向數組初始元素的指針,而不是指向數組的指針。 [請注意,這並不意味着var是一個指針 - 它非常是指針 - 它只是行爲像的指針在大多數表達式數組的第一元素]

這意味着在表達式var中通常衰減爲指向int的指針,而不是指向數組int的指針。

由於地址運算符(&)的操作數是不適用此衰減規則(另一個作爲sizeof運算符的操作數)的上下文。在這種情況下,&var的類型直接從var的類型派生,因此該類型是指向數組5 int的指針。

是的,指針具有相同的地址值(數組第一個元素的地址是數組本身的地址),但它們有不同的類型(int* vs int(*)[5]),因此在賦值中不兼容。

ISO/IEC 9899:1999 6.3.2.1/4:

除了當它是sizeof操作者或一元&操作者的操作數,或是用於初始化數組文本字符串,具有類型「類型數組」的表達式被轉換爲指向數組對象的初始元素的「指向類型的指針」類型的表達式,而不是左值。 ...

+0

我以爲數組在函數中調用時只會衰減爲指針。所以在表達中。 int arr [5] = {1,2,3,4,5}; int * ptr = arr;當分配給指針時,arry會衰減爲指針嗎? – ant2009 2010-08-18 06:43:33

+0

@robUK:這不僅僅是函數調用,它是發生衰減的大多數表達式上下文。用於初始化指針時數組會衰減;需要一個指針值來初始化一個指向「int」的指針,而不是一個「int」數組。 – 2010-08-18 09:09:34

3

代碼var本身是一個(*int),指向數組中的第一個元素。 C中的指針和數組非常相似。將int (*ptr)[5] = NULL;更改爲int* ptr = NULL;ptr = &var;改爲ptr = var;

1

從我可以告訴你分配一個數組指針(var)爲指向數組的指針((*ptr)[5])的指針,所以這就是爲什麼你會得到警告。

相反,嘗試使用

int *ptr = NULL; 
4

C是強類型語言。當函數期望int *類型的參數時,必須傳遞int *類型的參數。不是double *,而不是char *,但int *。即使double *char *中的實際數字地址與您想要傳遞的地址「相同」,但它仍然不會改變任何內容 - 您仍然必須通過int *。該語言禁止你傳遞錯誤類型的值。

這正是你的情況。該函數採用int (*)[5]類型的參數。這意味着你必須通過該類型的參數。不允許傳遞int *。地址是否一樣無差別。

相關問題