webentwicklung-frage-antwort-db.com.de

Übergeben eines Arrays als Argument an eine Funktion in C

Ich habe eine Funktion geschrieben, die Array als Argument, Enthält.

void arraytest(int a[])
{
    // changed the array a
    a[0]=a[0]+a[1];
    a[1]=a[0]-a[1];
    a[0]=a[0]-a[1];
}

void main()
{
    int arr[]={1,2};
    printf("%d \t %d",arr[0],arr[1]);
    arraytest(arr);
    printf("\n After calling fun arr contains: %d\t %d",arr[0],arr[1]);
}

Was ich gefunden habe ist, obwohl ich arraytest() function durch Übergeben von Werten aufrufe, die ursprüngliche Kopie von int arr[] wird geändert.

Kannst du bitte erklären warum?

60
Mohan Mahajan

Wenn Sie ein Array als Parameter übergeben, geben Sie dies ein

void arraytest(int a[])

bedeutet genau dasselbe wie

void arraytest(int *a)

so dass Sie are die Werte in main ändern.

Aus historischen Gründen sind Arrays keine erstklassigen Bürger und können nicht als Wert übergeben werden.

91
Bo Persson

Sie übergeben das Array nicht als Kopie. Es ist nur ein Zeiger, der auf die Adresse zeigt, an der das erste Element gespeichert ist.

6
fyr

Sie übergeben die Adresse des ersten Elements des Arrays

6
obo

In C "dekays" ein Array-Verweis auf ein Zeiger auf das erste Element des Arrays, mit Ausnahme einiger Sonderfälle. Daher ist es nicht möglich, ein Array "nach Wert" zu übergeben. Ein Array in einem Funktionsaufruf wird als Zeiger an die Funktion übergeben. Dies ist analog zur Weitergabe des Arrays durch Referenz.

BEARBEITEN: Es gibt drei solcher Sonderfälle, in denen ein Array nicht in einen Zeiger auf sein erstes Element zerfällt:

  1. sizeof a ist nicht das Gleiche wie sizeof (&a[0]).
  2. &a ist nicht dasselbe wie &(&a[0]) (und nicht ganz dasselbe wie &a[0]).
  3. char b[] = "foo" ist nicht das Gleiche wie char b[] = &("foo").
6
Thom Smith

Sie übergeben den Wert des Speicherplatzes des ersten Mitglieds des Arrays.

Wenn Sie also das Array innerhalb der Funktion ändern, ändern Sie das ursprüngliche Array.

Denken Sie daran, dass a[1]*(a+1) ist. 

4
alex

Arrays in C werden in den meisten Fällen in einen Zeiger auf das erste Element des Arrays selbst konvertiert. Und detailliertere Arrays, die in Funktionen übergeben werden, werden immer in Zeiger konvertiert. 

Hier ein Zitat aus K & R2nd :

Wenn ein Array-Name an eine Funktion übergeben wird, wird die .__ übergeben. Ort des ursprünglichen Elements. Innerhalb der aufgerufenen Funktion ist dies Argument ist eine lokale Variable, und ein Array-Name-Parameter ist daher eine Zeiger, dh eine Variable, die eine Adresse enthält. 

Schreiben:

void arraytest(int a[])

hat die gleiche Bedeutung wie das Schreiben:

void arraytest(int *a)

Obwohl Sie nicht explizit schreiben, ist es so, wie Sie einen Zeiger übergeben und die Werte im Main ändern.

Für mehr empfehle ich wirklich zu lesen dies .

Weitere Antworten finden Sie unter SO hier

3
granmirupa

Wenn Sie ein Single-Dimension-Array als Argument in einer Funktion übergeben möchten, müssen Sie einen formalen Parameter auf eine der folgenden drei Arten deklarieren, und alle drei Deklarationsmethoden liefern ähnliche Ergebnisse, da jeder den Compiler anweist dass ein Integerzeiger empfangen wird .

int func(int arr[], ...){
    .
    .
    .
}

int func(int arr[SIZE], ...){
    .
    .
    .
}

int func(int* arr, ...){
    .
    .
    .
}

Sie ändern also die ursprünglichen Werte.

Vielen Dank !!!

3

Übergabe eines mehrdimensionalen Arrays als Argument an eine Funktion. Das Übergeben eines eindimensionalen Arrays als Argument ist mehr oder weniger trivial . Lassen Sie uns einen interessanteren Fall des Übergebens eines zweidimensionalen Arrays betrachten. In C können Sie keinen Zeiger auf Zeiger verwenden Konstrukt (int **) anstelle von 2 dim array . Lassen Sie uns ein Beispiel machen:

void assignZeros(int(*arr)[5], const int rows) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < 5; j++) {
            *(*(arr + i) + j) = 0;
            // or equivalent assignment
            arr[i][j] = 0;
        }
    }

Hier habe ich eine Funktion angegeben, die als erstes Argument einen Zeiger auf ein Array von 5 Ints enthält. Ich kann jedes 2-Dim-Array mit 5 Spalten als Argument übergeben:

int arr1[1][5]
int arr1[2][5]
...
int arr1[20][5]
...

Vielleicht möchten Sie eine allgemeinere Funktion definieren, die alle 2-Dim-Arrays akzeptiert und die Funktionssignatur wie folgt ändert:

void assignZeros(int ** arr, const int rows, const int cols) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            *(*(arr + i) + j) = 0;
        }
    }
}

Dieser Code würde kompilieren, aber Sie erhalten einen Laufzeitfehler, wenn Sie versuchen, die Werte auf dieselbe Weise wie in der ersten Funktion .. zuzuweisen. In C sind multidimensionale Arrays nicht dasselbe wie Zeiger auf Zeiger ... auf Zeiger. Ein int (* arr) [5] ist ein Zeiger auf ein Array von 5 Elementen, Int (* arr) [6] ist ein Zeiger auf ein Array von 6 Elementen, und sie sind Zeiger auf verschiedene Typen!

Nun, wie können Funktionsargumente für höhere Dimensionen definiert werden? Ganz einfach, wir folgen einfach dem Muster! Hier ist die gleiche Funktion angepasst, um ein Array von 3 Dimensionen aufzunehmen:

void assignZeros2(int(*arr)[4][5], const int dim1, const int dim2, const int dim3) {
    for (int i = 0; i < dim1; i++) {
        for (int j = 0; j < dim2; j++) {
            for (int k = 0; k < dim3; k++) {
                *(*(*(arr + i) + j) + k) = 0;
                // or equivalent assignment
                arr[i][j][k] = 0;
            }
        }
    }
}

Wie zu erwarten, können 3 Dim-Arrays als Argument verwendet werden, die in den zweiten Dimensionen 4 Elemente und in der dritten Dimension 5 Elemente haben. So etwas wäre in Ordnung:

arr[1][4][5]
arr[2][4][5]
...
arr[10][4][5]
...

Wir müssen jedoch alle Maßgrößen bis zur ersten Größe angeben.

@Bo Persson sagt richtig in seiner großartigen Antwort hier

=================================================

Wenn Sie ein Array als Parameter übergeben, geben Sie dies ein

void arraytest(int a[])

bedeutet genau dasselbe wie

void arraytest(int *a)

=================================================

Lassen Sie mich jedoch noch hinzufügen, dass es:

bedeutet genau dasselbe wie

void arraytest(int a[0])

was genau dasselbe bedeutet wie

void arraytest(int a[1])

was genau dasselbe bedeutet wie

void arraytest(int a[2])

was genau dasselbe bedeutet wie

void arraytest(int a[1000])

usw.

Tatsächlich dient der "size" -Wert innerhalb des Array-Parameters hier offenbar nur zu Zwecken der Ästhetik/Selbstdokumentation und kann eine beliebige positive ganze Zahl (size_t type) sein, die ich denke! 

In der Praxis sollten Sie jedoch die Mindestgröße des Arrays angeben, das die Funktion erwartet, sodass Sie beim Schreiben von Code leicht nachverfolgen und überprüfen können. Der MISRA-C-2012 Standard ( Kaufen/Laden Sie die 236-pg 2012-Version PDF des Standards für £ 15.00 hier ) so weit, zu sagen: 

Regel 17.5 Das Funktionsargument, das einem Parameter entspricht, für den ein Array-Typ deklariert wurde, muss eine entsprechende Anzahl von Elementen enthalten.

...

Wenn ein Parameter als Array mit einer angegebenen Größe deklariert ist, sollte das entsprechende Argument in jedem Funktionsaufruf auf ein Objekt verweisen, das mindestens so viele Elemente wie das Array enthält.

...

Die Verwendung eines Array-Deklarators für einen Funktionsparameter gibt die Funktionsschnittstelle klarer an als die Verwendung eines Zeigers. Die minimale Anzahl der von der Funktion erwarteten Elemente wird explizit angegeben, während dies mit einem Zeiger nicht möglich ist. [Betonung hinzugefügt]

Mit anderen Worten, sie empfehlen die Verwendung des expliziten Größenformats, auch wenn der C-Standard es technisch nicht erzwingt --es hilft zumindest, Ihnen als Entwickler und anderen, die den Code verwenden, zu klären, welche Größe das Array hat Funktion erwartet, dass Sie weitergeben.

0
Gabriel Staples