Übergeben Sie ein Array nach Wert an eine Funktion
Lesezeit: 9 Minuten
Zuzu
Nachfolgend ein Ausschnitt aus dem Buch C-Programmierung Nur die FAQs. Ist das nicht falsch, da Arrays niemals als Wert übergeben werden können?
VIII.6: Wie kann man ein Array per Wert an eine Funktion übergeben?
Antworten: Ein Array kann per Wert an eine Funktion übergeben werden, indem in der aufgerufenen Funktion der Arrayname mit eckigen Klammern ([ and ]) am Ende angehängt. Übergeben Sie beim Aufrufen der Funktion einfach die Adresse des Arrays (also den Namen des Arrays) an die aufgerufene Funktion. Beispielsweise übergibt das folgende Programm das Array x[] zur benannten Funktion byval_func() nach Wert:
Das int[] -Parameter teilt dem Compiler mit, dass die byval_func()
Die Funktion akzeptiert ein Argument – ein Array von Ganzzahlen. Wenn der byval_func() Funktion aufgerufen wird, übergeben Sie die Adresse des Arrays an byval_func():
byval_func(x);
Da das Array als Wert übergeben wird, wird eine exakte Kopie des Arrays erstellt und auf dem Stapel abgelegt. Die aufgerufene Funktion erhält dann diese Kopie des Arrays und kann sie ausdrucken. Weil das Array übergeben wurde byval_func() ist eine Kopie des ursprünglichen Arrays, wobei das Array innerhalb des geändert wird byval_func() Die Funktion hat keine Auswirkung auf das ursprüngliche Array.
Dies gilt für Strukturen – Sie können sie als Wert (über den Stapel) oder als Referenz übergeben, aber nicht für Arrays.
– Sinus
23. Januar 2011 um 15:07 Uhr
Das ist in einem Buch über C, wirklich? Ich sehe, es stammt aus dem Jahr 1995, aber das war damals schon schlichtweg falsch.
– Jens Gustedt
23. Januar 2011 um 16:11 Uhr
Wenn das so in dem Buch steht, müssen Sie das Buch wegschmeißen – es enthält ernsthafte Fehlinformationen zu einem grundlegenden Thema, und wer weiß, welche anderen Fehlinformationen zu welchen anderen Themen. Der letzte zitierte Absatz ist Unsinn – wenn Sie das Array in der aufgerufenen Funktion ändern, ändern Sie auch das Array in der aufrufenden Funktion, da Arrays in C nicht als Wert übergeben werden.
– Jonathan Leffler
23. Januar 2011 um 16:17 Uhr
Schlicht falsch..
– kein Benutzer
19. Oktober 2017 um 15:09 Uhr
“Wenn der byval_func() Funktion aufgerufen wird, übergeben Sie die Adresse des Arrays an byval_func():” – Dies ist der einzige halbrichtige Satz aus diesem Zitat. Ich frage mich, warum nicht einer der 5 Autoren oder mindestens einer der 7 Korrektoren auf diesen Satz gestoßen ist und ihn richtig bewertet hat.
– RobertS unterstützt Monica Cellio
9. März 2020 um 14:02 Uhr
Peter Török
Da das Array als Wert übergeben wird, wird eine exakte Kopie des Arrays erstellt und auf dem Stapel abgelegt.
Das ist falsch: das Array selbst wird nicht kopiert, wird nur eine Kopie des Zeigers auf seine Adresse an den Aufgerufenen übergeben (auf dem Stapel abgelegt). (Unabhängig davon, ob Sie den Parameter als int[] oder int*es zerfällt in einen Zeiger.) Dadurch können Sie den Inhalt des Arrays innerhalb der aufgerufenen Funktion ändern. Also das
Weil das Array übergeben wurde byval_func() ist eine Kopie des ursprünglichen Arrays, wobei das Array innerhalb des geändert wird byval_func() Die Funktion hat keine Auswirkung auf das ursprüngliche Array.
ist einfach falsch (ein großes Lob an @Jonathan Leffler für seinen Kommentar unten). Eine Neuzuweisung des Zeigers innerhalb der Funktion ändert jedoch nicht den Zeiger auf das ursprüngliche Array außerhalb der Funktion.
Er ist es in der Tat. In C++ können Sie natürlich Array-Objekte als Wert übergeben lassen, aber in C ist ein Array nur ein Zeiger.
– Stefan H. Sänger
23. Januar 2011 um 15:07 Uhr
StefanHållén: Sie können Arrays weder in C noch in C++ als Wert übergeben (oder zurückgeben), Sie können Arrays in C++ als Referenz übergeben, weil C++ Referenztypen hat.
– CB Bailey
23. Januar 2011 um 15:09 Uhr
Ich meinte, dass Sie zum Beispiel std::array verwenden könnten. Instanzen davon können als Wert übergeben und zurückgegeben werden.
– Stefan H. Sänger
23. Januar 2011 um 15:11 Uhr
@StefanHållén: Bitte beachten Sie das Tag, dies ist eine C-Frage.
– CB Bailey
23. Januar 2011 um 15:25 Uhr
Ich würde weiter gehen; Obwohl der von Ihnen zitierte Satz leicht zweideutig ist und wohltätig als richtig ausgelegt werden könnte, ist der letzte Satz im Sinne des Begriffs „Ändern des Arrays“ einfach falsch. Wenn die aufgerufene Funktion schreibt array[0]es modifiziert array[0] in der aufrufenden Funktion – unter der offensichtlichen Aufrufnotation.
– Jonathan Leffler
23. Januar 2011 um 16:25 Uhr
Lundin
Verbrenne dieses Buch. Wenn Sie eine echte C-FAQ wollen, die nicht von einem Programmieranfänger geschrieben wurde, verwenden Sie diese hier: http://c-faq.com/aryptr/index.html.
Syntaxtechnisch genau genommen Sie kann nicht Übergeben Sie ein Array nach Wert in C.
void func (int* x); /* this is a pointer */
void func (int x[]); /* this is a pointer */
void func (int x[10]); /* this is a pointer */
Jedoch, für die Aufzeichnung gibt es einen schmutzigen Trick in C, der es Ihnen erlaubt, ein Array als Wert in C zu übergeben. Versuchen Sie das nicht zu Hause! Denn trotz dieses Tricks gibt es nie einen Grund, ein Array als Wert zu übergeben.
Kosmetik für 3. Beispiel bedeutet, dass Sie eine tun können sizeof(array)/sizeof(array[0]) in der Funktion
– Ulterior
29. Juni 2012 um 3:17 Uhr
@Ulterior Wäre das nicht schön, wenn es funktionieren würde? Aber leider irren Sie sich, der C-Standard ist nicht so schlau. Versuche dies: void func (int arr[10]) { printf("No, I am still a pointer, my size is %d.", sizeof(arr)); }. Auf einem PC werden 4 oder 8 gedruckt, nicht 40, wie Sie erwarten würden.
– Ludin
11. Dezember 2012 um 10:01 Uhr
“Denn trotz dieses Tricks gibt es immer noch keinen Grund, ein Array als Wert zu übergeben.” — warum?
– Benutzer1300214
23. Januar 2013 um 10:50 Uhr
@pbs Nehmen wir an, Sie haben ein 32-Bit-System und ein Array von 10 Ints. Sie können einen Zeiger übergeben, 4 Byte Speicher belegen und das Programm schnell laufen lassen, oder Sie können den obigen schmutzigen Trick verwenden, 40 Byte Speicher belegen und das Programm langsam laufen lassen. Wenn Sie ein Array als Wert übergeben, können Sie es außerdem nicht ändern, sodass der Aufrufer die Änderung bemerkt.
– Ludin
24. Januar 2013 um 17:47 Uhr
@Lundin Ich stimme zu, dass dies besser ist, wenn es möglich ist. Was aber, wenn ein Algorithmus auf jeder Ebene eines Baums unterschiedliche Kopien des Arrays benötigt? Ich habe einen Algorithmus geschrieben, bei dem für jeden Knoten eines aufgerufenen Baums eine Kopie einer Anzahl von Punkten erforderlich ist, und es gibt kein Vermeiden der verwendeten Speichermenge, da sonst die Punkte nicht verschieden wären, was erforderlich ist. Der einzige mögliche Nachteil ist, dass es in solchen Fällen möglicherweise schneller ist, den gesamten Speicher von Anfang an auf einmal zu allozieren … Wenn die erforderlichen Daten jedoch dynamisch sind, ist dies im Allgemeinen möglicherweise nicht möglich.
– Benutzer1300214
25. Januar 2013 um 13:20 Uhr
RobertS unterstützt Monica Cellio
Ist das nicht falsch, da Arrays niemals als Wert übergeben werden können?
Exakt. Sie können ein Array nicht als Wert in C übergeben.
Ich habe mir den zitierten Teil des Buches angesehen und die Quelle dieser Verwirrung oder dieses Fehlers ist ziemlich schnell gefunden.
Davon wusste der Autor nichts *i ist äquivalent zu i[] wenn es als Parameter für eine Funktion bereitgestellt wird. Letztere Form wurde erfunden, um dem Leser des Codes explizit zu veranschaulichen, dass i zeigt auf ein Array, das eine große Quelle der Verwirrung ist, wie diese Frage gut zeigt.
Was ich komisch finde, ist, dass der Autor den bestimmten Teil des Buches oder zumindest einen der anderen Teile (weil das Buch hat 5 Autoren insgesamt) oder einer der 7 Korrektoren haben zumindest den Satz nicht erwähnt:
“Wenn der byval_func() Funktion aufgerufen wird, übergeben Sie die Adresse des Arrays zu byval_func():”
Damit hätten sie zumindest merken müssen, dass es einen Konflikt gibt. Da Sie eine Adresse übergeben, ist es nur eine Adresse. Es passiert nichts auf magische Weise, was eine Adresse in ein ganz neues Array verwandelt.
Aber zurück zur Frage selbst:
Sie können ein Array, wie es in C ist, nicht als Wert übergeben, wie Sie selbst bereits zu wissen scheinen. Aber Sie können drei (es könnten noch mehr sein, aber das ist mein aktueller Stand) Dinge tun, die je nach Einzelfall eine Alternative sein könnten, also fangen wir an.
Kapseln Sie ein Array in einer Struktur (wie in anderen Antworten erwähnt):
#include <stdio.h>
struct a_s {
int a[20];
};
void foo (struct a_s a)
{
size_t length = sizeof a.a / sizeof *a.a;
for(size_t i = 0; i < length; i++)
{
printf("%d\n",a.a[i]);
}
}
int main()
{
struct a_s array;
size_t length = sizeof array.a / sizeof *array.a;
for(size_t i = 0; i < length; i++)
{
array.a[i] = 15;
}
foo(array);
}
Übergeben Sie den Zeiger, aber fügen Sie auch einen Parameter hinzu, um die Größe des Arrays zu bestimmen. In der aufgerufenen Funktion wird ein neues Array mit diesen Größeninformationen erstellt und mit den Werten aus dem Array im Aufrufer zugewiesen:
#include <stdio.h>
void foo (int *array, size_t length)
{
int b[length];
for(size_t i = 0; i < length; i++)
{
b[i] = array[i];
printf("%d\n",b[i]);
}
}
int main()
{
int a[10] = {0,1,2,3,4,5,6,7,8,9};
foo(a,(sizeof a / sizeof *a));
}
Vermeiden Sie es, lokale Arrays zu definieren, und verwenden Sie nur ein Array mit globalem Gültigkeitsbereich:
#include <stdio.h>
int a[10];
size_t length = sizeof a / sizeof *a;
void foo (void)
{
for(size_t i = 0; i < length; i++)
{
printf("%d\n",a[i]);
}
}
int main()
{
for(size_t i = 0; i < length; i++)
{
a[i] = 25;
}
foo();
}
In C und C++ ist es NICHT möglich, einen kompletten Speicherblock per Wert als Parameter an eine Funktion zu übergeben, aber wir dürfen seine Adresse übergeben. In der Praxis hat dies fast den gleichen Effekt und ist ein viel schnellerer und effizienterer Vorgang.
Um sicher zu gehen, können Sie die Array-Größe übergeben oder einen konstanten Qualifizierer vor den Zeiger setzen, um sicherzustellen, dass der Aufgerufene ihn nicht ändert.
Yuo kann es umgehen, indem er das Array in die Struktur einbettet
#include <stdint.h>
#include <stdio.h>
struct wrap
{
int x[1000];
};
struct wrap foo(struct wrap x)
{
struct wrap y;
for(int index = 0; index < 1000; index ++)
y.x[index] = x.x[index] * x.x[index];
return y;
}
int main ()
{
struct wrap y;
for(int index = 0; index < 1000; index ++)
y.x[index] = rand();
y = foo(y);
for(int index = 0; index < 1000; index ++)
{
printf("%d %s", y.x[index], !(index % 30) ? "\n" : "");
}
}
rauben
#include<stdio.h>
void fun(int a[],int n);
int main()
{
int a[5]={1,2,3,4,5};
fun(a,5);
}
void fun(int a[],int n)
{
int i;
for(i=0;i<=n-1;i++)
printf("value=%d\n",a[i]);
}
Mit dieser Methode können wir das Array nach Wert übergeben, aber tatsächlich greift das Array über seine Basisadresse zu, die tatsächlich in den Stapel kopiert wird.
14106200cookie-checkÜbergeben Sie ein Array nach Wert an eine Funktionyes
Dies gilt für Strukturen – Sie können sie als Wert (über den Stapel) oder als Referenz übergeben, aber nicht für Arrays.
– Sinus
23. Januar 2011 um 15:07 Uhr
Das ist in einem Buch über C, wirklich? Ich sehe, es stammt aus dem Jahr 1995, aber das war damals schon schlichtweg falsch.
– Jens Gustedt
23. Januar 2011 um 16:11 Uhr
Wenn das so in dem Buch steht, müssen Sie das Buch wegschmeißen – es enthält ernsthafte Fehlinformationen zu einem grundlegenden Thema, und wer weiß, welche anderen Fehlinformationen zu welchen anderen Themen. Der letzte zitierte Absatz ist Unsinn – wenn Sie das Array in der aufgerufenen Funktion ändern, ändern Sie auch das Array in der aufrufenden Funktion, da Arrays in C nicht als Wert übergeben werden.
– Jonathan Leffler
23. Januar 2011 um 16:17 Uhr
Schlicht falsch..
– kein Benutzer
19. Oktober 2017 um 15:09 Uhr
“Wenn der
byval_func()
Funktion aufgerufen wird, übergeben Sie die Adresse des Arrays anbyval_func()
:” – Dies ist der einzige halbrichtige Satz aus diesem Zitat. Ich frage mich, warum nicht einer der 5 Autoren oder mindestens einer der 7 Korrektoren auf diesen Satz gestoßen ist und ihn richtig bewertet hat.– RobertS unterstützt Monica Cellio
9. März 2020 um 14:02 Uhr