Übergeben Sie ein Array nach Wert an eine Funktion

Lesezeit: 9 Minuten

Benutzeravatar von Zuzu
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


Benutzeravatar von Péter Török
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

Benutzeravatar von Lundin
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.

typedef struct
{
  int my_array[10];
} Array_by_val;

void func (Array_by_val x);

  • 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 den Benutzeravatar von Monica Cellio
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.

  1. 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);
}
  1. Ü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));
}
  1. 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" : "");
    }


}

Benutzeravatar von Rob
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.

1410620cookie-checkÜbergeben Sie ein Array nach Wert an eine Funktion

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy