web-dev-qa-db-de.com

Warum muss die Spaltengröße angegeben werden, wenn ein 2D-Array als Parameter übergeben wird?

Warum kann mein Parameter nicht sein?

void example(int Array[][]){ /*statements*/}

Warum muss ich die Spaltengröße des Arrays angeben? Sagen Sie zum Beispiel 3

void example(int Array[][3]){/*statements*/}

Mein Professor sagte, es sei obligatorisch, aber ich programmierte vor Schulbeginn, und ich erinnerte mich daran, dass es keinen syntaktischen oder semantischen Fehler gab, als ich dies zu meinem Parameter machte. Oder habe ich etwas vermisst? 

32

Bei der Beschreibung von Parametern zerfallen Arrays immer in Zeiger auf ihr erstes Element.

Wenn Sie ein als int Array[3] deklariertes Array an die Funktion void foo(int array[]) übergeben, zerfällt es in einen Zeiger auf den Anfang des Arrays, d. H. int *Array;. Übrigens, Sie können einen Parameter als int array[3] oder int array[6] oder sogar int *array beschreiben - alle diese Werte sind gleichwertig und Sie können jedes Integer-Array problemlos übergeben.

Im Falle von Arrays von Arrays (2D-Arrays) zerfällt es auch zu einem Zeiger auf sein erstes Element, was zufällig ein eindimensionales Array ist, d. H. Wir bekommen int (*Array)[3]

Die Angabe der Größe ist wichtig. Wenn er nicht obligatorisch wäre, kann der Compiler beispielsweise nicht wissen, wie er mit dem Ausdruck Array[2][1] umgehen soll. 

Um zu demeferenzieren, dass ein Compiler den Versatz des Elements berechnen muss, benötigen wir einen zusammenhängenden Speicherblock (int Array[2][3] ist ein zusammenhängender Block von Ganzzahlen), was für Zeiger leicht sein sollte. Wenn a ein Zeiger ist, wird a[N] als start_address_in_a + N * size_of_item_being_pointed_by_a erweitert. Im Falle des Ausdrucks Array[2][1] innerhalb einer Funktion (wir möchten auf dieses Element zugreifen) ist Array ein Zeiger auf ein eindimensionales Array, und es gilt die gleiche Formel. Die Anzahl der Bytes in der letzten eckigen Klammer ist erforderlich, um size_of_item_being_pointed_by_a zu finden. Wenn wir nur Array[][] hätten, wäre es unmöglich, das herauszufinden und ein Array-Element, das wir benötigen, dereferenzieren zu können.

Ohne die Größe funktionieren Zeigerarithmetik nicht für Arrays von Arrays. Welche Adresse würde Array + 2 erzeugen: die Adresse in Array um 2 Bytes vorrücken (falsch) oder den Zeiger 3* sizeof(int) * 2 Bytes vorrücken?

30

In C/C++ werden sogar 2-D-Arrays nacheinander in einer Reihe nach im Speicher gespeichert. Wenn Sie also (in einer einzigen Funktion) haben:

int a[5][3];
int *head;

head = &a[0][0];
a[2][1] = 2; // <--

Das Element, auf das Sie tatsächlich mit a[2][1] zugreifen, ist *(head + 2*3 + 1). Dies geschieht sequentiell. Dieses Element befindet sich hinter 3 Elementen der 0-Zeile und 3 Elementen der 1-Zeile und dann noch einem weiteren Index.

Wenn Sie eine Funktion wie erklären:

void some_function(int array[][]) {...}

syntaktisch sollte es kein Fehler sein. Wenn Sie jetzt versuchen, auf array[2][3] zuzugreifen, können Sie nicht erkennen, auf welches Element zugegriffen werden soll. Auf der anderen Seite, wenn Sie:

void some_function(int array[][5]) {...}

sie wissen, dass mit array[2][3] festgestellt werden kann, dass Sie tatsächlich auf das Element an der Speicheradresse *(&array[0][0] + 2*5 + 3)weilzugreifen.

Es gibt eine weitere Option, wie zuvor vorgeschlagen, Sie können eine Funktion wie folgt deklarieren:

void some_function(int *array, int cols) { ... }

auf diese Weise rufen Sie die Funktion mit den gleichen "Informationen" wie zuvor auf - der Anzahl der Spalten. Sie greifen dann etwas anders auf die Array-Elemente zu: Sie müssen *(array + i*cols + j) dort schreiben, wo Sie normalerweise array[i][j] schreiben würden, denn array ist jetzt ein Zeiger auf Ganzzahl (nicht auf einen Zeiger).

Wenn Sie eine Funktion wie diese deklarieren, müssen Sie sie mit der Anzahl der Spalten aufrufen, die tatsächlich deklariert für das Array sind und nicht nur verwendet werden. Also zum Beispiel:

int main(){
   int a[5][5];
   int i, j;

   for (i = 0; i < 3; ++i){
       for (int j=0; j < 3; ++j){
           scanf("%d", &a[i][j]);
       }
   }

   some_function(&a[i][j], 5); // <- correct
   some_function(&a[i][j], 3); // <- wrong

   return 0;
}
11
penelope

Dazu gibt es einen ähnlichen Beitrag. Sie können unter link . Array in C erstellen und den Zeiger auf das Array an function Übergeben.

Andererseits muss der Compiler die zweite Dimension verwenden, damit er "Array" von einem Zeiger zum nächsten bewegen kann, da der gesamte Speicher linear angeordnet ist

0
Manik Sidana