2010-08-17 6 views
7

Ich habe folgendes Programm. Ich kann jedoch nicht verstehen, warum ich die Adresse des Arrays übergeben muss. Wenn beide auf dieselbe Adresse zeigen. Welches ist die Adresse des ersten Elements des Arrays von Int.Warum kann ich ein Array nicht direkt in C einem Zeiger zuweisen?

Ich erhalte eine Warnung, wenn ich versuche, und tun, um diese "Zuweisung von inkompatiblen Zeigertyp":

ptr = var; 

Der komplette Quellcode:

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; 
} 

ich den Code kompilieren mit gcc 4.4.4 c89 -Wall -Wextra -O0

+0

Ich habe versucht, Ihren Titel umzuschreiben, da es bedeutungslos war. Bitte überprüfen Sie, ob ich den Kern Ihres Problems richtig ausgewählt habe. –

+0

Ich denke, dein Titel klingt besser als meiner. Vielen Dank. – ant2009

+0

Sie Code-Snippet kompiliert fein. Meinst du, du würdest einen Fehler bekommen, wenn du 'ptr = var' zu main hinzugefügt hättest? –

Antwort

17

Es ist lediglich eine Art Thema.

In den meisten Ausdruck-Kontexten verfällt der Name eines Arrays (z. B. var) in einen Zeiger auf das ursprüngliche Element des Arrays, nicht in einen Zeiger auf das Array. [Beachten Sie, dass dies nicht bedeutet, dass var ein Zeiger - es ist viel sehr nicht ein Zeiger -. Es nur verhält wie ein Zeiger auf das erste Element des Arrays in den meisten Ausdrücke]

Dies bedeutet, dass in einem Ausdruck var normalerweise zu einem Zeiger auf int, kein Zeiger auf ein Array von int verfällt.

Da der Operand des Address-Of-Operators (&) ein Kontext ist, in dem diese Abklingregel nicht gilt (der andere ist als Operand des Operators sizeof). In diesem Fall wird der Typ &var direkt vom Typ var abgeleitet, so dass der Typ Zeiger auf Array von 5 int ist.

Ja, die Zeiger haben den gleichen Adresswert (die Adresse eines ersten Array-Elements ist die Adresse des Arrays selbst), aber sie haben unterschiedliche Typen (int* vs int(*)[5]), also sind nicht in der Zuordnung kompatibel.

ISO/IEC 9899: 1999 6.3.2.1/4:

Außer wenn es der Operand des sizeof Betreibers oder des unären & Operator oder ein Stringliteral verwendet, um ein Array zu initialisieren, ein Ausdruck mit dem Typ "array of type" wird in einen Ausdruck vom Typ "pointer to type" konvertiert, der auf das ursprüngliche Element des Array-Objekts zeigt und kein lvalue ist. ...

+0

Ich dachte, dass Arrays nur in Zeigern zerfallen, wenn sie in einer Funktion aufgerufen werden. also im Ausdruck. int arr [5] = {1,2,3,4,5}; int * ptr = arr; Der arry würde in einen Zeiger verfallen, wenn er einem Zeiger zugewiesen wird? – ant2009

+0

@robUK: Es sind nicht nur Funktionsaufrufe, sondern die meisten Ausdruckskontexte, in denen der Verfall auftritt. Das Array verfällt, wenn es zum Initialisieren eines Zeigers verwendet wird; Ein Zeigerwert wird benötigt, um einen Zeiger auf "int" zu initialisieren, nicht ein Array von "int". –

3

var selbst ist ein (*int) zeigt auf das erste Element in Ihrem Array. Zeiger und Arrays in C sind extrem ähnlich. Ändern int (*ptr)[5] = NULL; zu int* ptr = NULL; und ptr = &var; zu ptr = var;

1

Von dem, was ich sagen kann man ein Array Zeiger (var) auf einen Zeiger zuweisen, die zu einem Array-Zeiger verweist ((*ptr)[5]), ist also, warum Sie diese Warnung erhalten.

Stattdessen versuchen

int *ptr = NULL; 
4

C verwendet, ist eine stark typisierte Sprache.Wenn eine Funktion einen Parameter vom Typ int * erwartet, müssen Sie ein Argument vom Typ int * übergeben. Nicht double *, nicht char *, aber int *. Selbst wenn die tatsächliche numerische Adresse in diesen double * oder char * "dieselbe" ist wie die, die Sie übergeben möchten, ändert es immer noch nichts - Sie müssen immer noch eine int * übergeben. Die Sprache verbietet es, den Wert eines falschen Typs zu übergeben.

Genau das passiert in Ihrem Fall. Die Funktion übernimmt einen Parameter vom Typ int (*)[5]. Das bedeutet, dass Sie das Argument dieses Typs übergeben müssen. Das Übergeben einer int * stattdessen ist nicht erlaubt. Ob die Adresse gleich ist, macht keinen Unterschied.

Verwandte Themen