Wie erstelle ich einen Array-Rückgabetyp aus einer C-Funktion?

Lesezeit: 7 Minuten

Ich habe versucht, den Array-Namen wie unten gezeigt zurückzugeben. Grundsätzlich versuche ich, den Funktionstest dazu zu bringen, ein Array zurückzugeben, das in main verwendet werden kann. Können Sie mir raten, was ich genauer lesen muss, um herauszufinden, wie eine Funktion wie diese ausgeführt wird?

#include <stdio.h>

int test(int size, int x){
    int factorFunction[size];    
    factorFunction[0] = 5 + x;
    factorFunction[1] = 7 + x;
    factorFunction[2] = 9 + x;
    return factorFunction;
}

int main(void){
    int factors[2];
    factors = test(2, 3);
    printf("%d", factors[1]);
    return 0;
}

Ich erhalte die Compiler-Fehler:

smallestMultiple.c:8: warning: return makes integer from pointer without a cast
smallestMultiple.c:8: warning: function returns address of local variable
smallestMultiple.c: In function ‘main’:
smallestMultiple.c:13: error: incompatible types in assignment

  • schon viele tolle Antworten. Nur eine kurze Anmerkung von mir: Denken Sie daran: factorFunction bezieht sich auf “die Adresse des ersten (oder nullten) Elements Ihres Arrays.” Es ist äquivalent zu &factorFunction[0] was übersetzt “die Adresse des 0. Elements” bedeutet.

    – wpp

    12. Januar 2013 um 22:33 Uhr


  • Hallo Danke für den Kommentar! Ich verstehe das, ich wollte nur 1 auf eine tatsächliche Zahl 1 beziehen. Wird es als schlechte Praxis angesehen, den 0. Index zu ignorieren?

    – Benutzer1530249

    12. Januar 2013 um 23:04 Uhr

  • Sie sollten das 0-te Element nicht außer Acht lassen! Es ist etwas gewöhnungsbedürftig, aber unerlässlich (sogar für höhere Sprachen wie Ruby).

    – wpp

    13. Januar 2013 um 11:58 Uhr

Benutzer-Avatar
Oliver Charlesworth

Funktionen können in C keine Arrays zurückgeben.

Sie können jedoch Strukturen zurückgeben. Und Strukturen können Arrays enthalten …

  • Sie können ein Array in C zurückgeben, indem Sie die Zeigerrückgabefunktion verwenden.

    – Mohd Shibli

    1. Januar 2018 um 2:34 Uhr

  • @MohdShibli – Du kannst, aber typtechnisch ist das nicht ganz dasselbe. Und die Rückgabe eines Zeigers auf (sagen wir) ein lokales Array würde zu UB führen, also muss man das umgehen.

    – Oliver Charlesworth

    1. Januar 2018 um 10:05 Uhr

  • Das lokale Array-Problem kann leicht gelöst werden, indem das lokale Array statisch gemacht wird.

    – Mohd Shibli

    2. Januar 2018 um 2:07 Uhr

  • @MohdShibli – das ist in den meisten Fällen nicht wirklich eine Lösung. Statiken sind Singletons, was bedeutet, dass Sie das Ergebnis des ersten Funktionsaufrufs nicht weiter verwenden können, nachdem Sie es ein zweites Mal aufgerufen haben.

    – Oliver Charlesworth

    2. Januar 2018 um 12:17 Uhr

  • Die Rückgabe eines automatischen Arrays ist in C nicht erlaubt (sogar als Zeiger gecastet), aber C erlaubt die Rückgabe einer automatischen Struktur. Interessante Regel. Neugierig auf die Motivation dahinter

    – torez233

    8. März um 3:14

Sie können ein Array zurückgeben, indem Sie einen Zeiger zurückgeben (Arrays zerfallen zu Zeigern). Das wäre in Ihrem Fall jedoch schlecht, da Sie dann einen Zeiger auf eine lokale Variable zurückgeben würden, was zu einem undefinierten Verhalten führt. Dies liegt daran, dass der Speicher, auf den der zurückgegebene Zeiger zeigt, nach der Rückkehr der Funktion nicht mehr gültig ist, da der Stapelspeicher jetzt von anderen Funktionen wiederverwendet wird.

Was Sie tun sollten, ist, das Array und seine Größe als Argumente an die Funktion zu übergeben.

Sie haben auch ein anderes Problem in Ihrem Code, und das ist, dass Sie ein Array der Größe zwei verwenden, aber in a schreiben dritte Element.

Sie müssen Speicher auf dem Heap zuweisen und einen Zeiger zurückgeben. C kann keine Arrays von Funktionen zurückgeben.

int* test(int size, int x)
{
    int* factorFunction = malloc(sizeof(int) * size);    
    factorFunction[0] = 5 + x;
    factorFunction[1] = 7 + x;
    factorFunction[2] = 9 + x;
    return factorFunction;
}

  • Das ist nicht dasselbe. Arrays sind zusammenhängende Speicherblöcke auf dem Stack, die Raumlokalität garantieren. malloc garantiert nicht nur keine räumliche Lokalität (ein malloc kann weit von jedem anderen malloc entfernt sein), sondern kann auch fehlschlagen, wenn Sie nicht genügend Speicher haben. Daher ist es nicht die Antwort auf diese spezielle Frage, sondern eine andere Möglichkeit, einen Plural aus einer Funktion zurückzugeben, aber das ist nicht die Frage.

    – Dmitri

    27. August 2016 um 17:26 Uhr

Die erste Zeile der Fehlermeldungen bedeutet genau das, was sie sagt: Sie haben die Funktion so deklariert, dass sie eine zurückgibt intaber Sie versuchen, einen Zeiger zurückzugeben.
Das größere Problem (wie Ihnen die zweite Zeile der Fehlermeldungen sagt) besteht darin, dass das Array, auf das Sie einen Zeiger zurückgeben möchten, ein lokales Array ist und daher den Gültigkeitsbereich verlässt, wenn die Funktion zurückkehrt und nicht mehr gültig ist.
Was Sie tun sollten, ist ein Array (dh einen Teil des kontinuierlichen Speichers) mithilfe von dynamisch zuzuweisen malloc oder new und einen Zeiger darauf zurückgeben. Und stellen Sie natürlich sicher, dass Sie den Speicher freigeben, wenn Sie damit fertig sind.

Benutzer-Avatar
Dmitri

Leider unterstützt C weder die Rückgabe beliebiger Arrays noch anonymer Strukturen aus Funktionen, aber es gibt zwei Problemumgehungen.

Die erste Problemumgehung besteht darin, eine Struktur zu erstellen, die das Array enthält. Es wird die gleiche Größe wie das Array haben und auf dem Stapel zugewiesen werden, um die Lokalität des Speicherplatzes sicherzustellen.

z.B

typedef struct {
    int arr[5];
} my_array1;

typedef struct {
    int values[3];
} factorFunctionReturnType_t;

Die zweite Problemumgehung besteht darin, einen statischen Speicherpool zu erfinden (z. B. Array mit benutzerdefiniertem malloc/free nur für dieses Array), und dies ermöglicht Ihnen effektiv, wieder dynamisch Speicher aus diesem Pool zuzuweisen, wodurch effektiv ein Zeiger auf zusammenhängenden Stapelspeicherplatz zurückgegeben wird ist per Definition ein Array.

z.B

#include <stdint.h>
static uint8_t static_pool[2048];

Implementieren Sie dann my_alloc, my_free, die diesen spezifischen Speicherpool verwalten, und stellen Sie erneut sicher, dass sich der erstellte Speicher auf dem Stapel befindet und der Speicher bereits von vornherein Ihrer Anwendung gehört (während malloc möglicherweise Speicher zuweist, auf den die Anwendung zuvor nicht zugreifen konnte, oder abstürzt, wenn nicht genügend Speicher vorhanden ist und nicht auf Fail Return geprüft).

Die dritte Problemumgehung besteht darin, dass die Funktion eine lokale Variable an eine Rückruffunktion zurückgibt; Dadurch wird sichergestellt, dass Sie nach Abschluss der Funktion das Ergebnis verwenden können, ohne den Stack zu beschädigen, da die Funktion, die den Speicher verwendet, über dem Bereich sitzt, der den Stack enthält.

#include <stdint.h>
#include <stdio.h>

void returnsAnArray(void (*accept)(void *)) {
    char result[] = "Hello, World!";    

    accept(result);
}

void on_accept(void *result) {
    puts((char *)result);
}

int main(int argc, char **argv)
{
    returnsAnArray(on_accept);

    return 0;
}

Dies ist effizienter als ein nicht stapelartiger Speicherpool, der Entscheidungen treffen muss, um eine Fragmentierung zu vermeiden, effizienter als ein stapelartiger Speicherpool, der das Ergebnis einfach auf den Stapel legt, weil er die Zeichenfolge nicht kopieren muss, und mehr threadsicher, da der Rückgabewert der Funktion nicht riskiert, von einem anderen Thread überschrieben zu werden (es sei denn, es wird eine Sperre verwendet).

Das Lustige ist, dass alle Programme des “funktionalen Programmierparadigmas” am Ende betonen, dass Sie C-Programme ohne Malloc schreiben können, indem Sie Callback-Funktionen verketten und effektiv auf dem Stapel zuweisen.

Dies hat einen interessanten Nebeneffekt, indem verknüpfte Listen nicht mehr cache-feindlich gemacht werden (da auf dem Stack zugewiesene Callback-verknüpfte Listen alle auf dem Stack nahe beieinander liegen werden, wodurch Sie Dinge wie Laufzeit-String-Manipulationen ohne Mallocs und letzt Sie haben Benutzereingaben unbekannter Größe aufgebaut, ohne Mallocs auszuführen.

Benutzer-Avatar
Howard J

C empfiehlt nicht, die Adresse einer lokalen Variablen außerhalb der Funktion zurückzugeben, also müssten Sie die lokale Variable als statische Variable definieren.

#include <stdio.h>

/* function to generate and return random numbers */
int * getRandom( ) {

   static int  r[10];
   int i;

   /* set the seed */
   srand( (unsigned)time( NULL ) );

   for ( i = 0; i < 10; ++i) {
      r[i] = rand();
      printf( "r[%d] = %d\n", i, r[i]);
   }

   return r;
}

/* main function to call above defined function */
int main () {

   /* a pointer to an int */
   int *p;
   int i;

   p = getRandom();

   for ( i = 0; i < 10; i++ ) {
      printf( "*(p + %d) : %d\n", i, *(p + i));
   }

   return 0;
}

Benutzer-Avatar
Matt Petersson

Mein Vorschlag wäre, ein Array zum Ausfüllen zu übergeben:

void test(int size, int factors[], int x){
    factorFunction[0] = 5 + x;
    factorFunction[1] = 7 + x;
    factorFunction[2] = 9 + x;
}

int main(void){
    int factors[3];
    test(3, factors, 3);
    printf("%d", factors[1]);
    return 0;
}

Bei dieser Methode müssen Sie sich keine Gedanken über die Zuweisung machen und müssen das Array später nicht freigeben.

Ich habe auch die Größe des Arrays angepasst, damit Sie nicht mit dem dritten Element außerhalb davon schreiben. Denken Sie daran, dass C-Arrays mit “wie viele Sie wollen” deklariert und dann von indiziert werden 0 ... (how_many-1)Also [2] auf einem Array deklariert mit [2] geht außerhalb des Arrays.

1138150cookie-checkWie erstelle ich einen Array-Rückgabetyp aus einer C-Funktion?

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

Privacy policy