Ich bin relativ neu in C und brauche Hilfe bei Methoden, die mit Arrays umgehen. Da ich aus der Java-Programmierung komme, bin ich es gewohnt zu sagen int [] method()um ein Array zurückzugeben. Ich habe jedoch herausgefunden, dass Sie bei C Zeiger für Arrays verwenden müssen, wenn Sie sie zurückgeben. Als neuer Programmierer verstehe ich das wirklich überhaupt nicht, selbst bei den vielen Foren, die ich durchgesehen habe.
Grundsätzlich versuche ich, eine Methode zu schreiben, die ein char-Array in C zurückgibt. Ich werde die Methode (nennen wir sie returnArray) mit einem Array bereitstellen. Es erstellt ein neues Array aus dem vorherigen Array und gibt einen Zeiger darauf zurück. Ich brauche nur etwas Hilfe, wie ich damit anfangen kann und wie ich den Zeiger lesen kann, sobald er aus dem Array gesendet wird. Jede Hilfe, die dies erklärt, wird geschätzt.
Vorgeschlagenes Codeformat für die Array-Rückgabefunktion
char *returnArray(char array []){
char returned [10];
//methods to pull values from array, interpret them, and then create new array
return &(returned[0]); //is this correct?
}
Aufrufer der Funktion
int main(){
int i=0;
char array []={1,0,0,0,0,1,1};
char arrayCount=0;
char* returnedArray = returnArray(&arrayCount); ///is this correct?
for (i=0; i<10;i++)
printf(%d, ",", returnedArray[i]); //is this correctly formatted?
}
Ich habe das noch nicht getestet, da mein C-Compiler im Moment nicht funktioniert, aber ich würde das gerne herausfinden
Hat das Rückgabearray eine bekannte Größe, wie in Ihrem Codebeispiel angegeben? Das einzige andere Problem, das ich neben den in den Antworten erwähnten Stack-Problemen sehe, ist, dass Sie nicht wissen, wie groß es ist, wenn Ihr Rückgabe-Array eine unbestimmte Größe hat, da Zeiger/Arrays in C funktionieren.
– seltsame freie Welt
25. Juli 2012 um 18:56 Uhr
Ja, ich kenne die Größe des eingehenden Arrays jederzeit. Die Größe des Eingabe- und Ausgabearrays ändert sich nicht.
Sie können keine Arrays von Funktionen in C zurückgeben. Sie können (sollten) dies auch nicht tun:
char *returnArray(char array []){
char returned [10];
//methods to pull values from array, interpret them, and then create new array
return &(returned[0]); //is this correct?
}
returned wird mit automatischer Speicherdauer erstellt und Verweise darauf werden ungültig, sobald es seinen Deklarationsbereich verlässt, dh wenn die Funktion zurückkehrt.
Sie müssen den Speicher innerhalb der Funktion dynamisch zuweisen oder einen vorab zugewiesenen Puffer füllen, der vom Aufrufer bereitgestellt wird.
Option 1:
Weisen Sie den Speicher innerhalb der Funktion dynamisch zu (Aufrufer, der für die Freigabe verantwortlich ist ret)
int main() {
char *p = foo(10);
if(p) {
// do stuff with p
free(p);
}
return 0;
}
Option 2:
Füllen Sie einen vorab zugewiesenen Puffer, der vom Aufrufer bereitgestellt wird (Aufrufer weist zu buf und geht an die Funktion über)
void foo(char *buf, int count) {
for(int i = 0; i < count; ++i)
buf[i] = i;
}
Und nenne es so:
int main() {
char arr[10] = {0};
foo(arr, 10);
// No need to deallocate because we allocated
// arr with automatic storage duration.
// If we had dynamically allocated it
// (i.e. malloc or some variant) then we
// would need to call free(arr)
}
Option 3: (ein statisches Array)
– muuuuh
25. Juli 2012 um 18:55 Uhr
@moooeeeep: Ja, ich habe das absichtlich weggelassen, um die Dinge einfach zu halten, aber ja, Sie können einen Zeiger auf statische Daten zurückgeben, die innerhalb der Funktion deklariert wurden.
– Ed S.
25. Juli 2012 um 18:56 Uhr
@ user1506919: Ich würde eigentlich Option 2 bevorzugen, da klar ist, wer Speicher zuweist und freigibt, aber ich füge ein Beispiel für Sie hinzu.
– Ed S.
25. Juli 2012 um 19:02 Uhr
Option 4: Gibt eine Struktur zurück, die ein Array fester Größe enthält.
– Todd Lehmann
21. Mai 2015 um 0:10 Uhr
Option 5: Geben Sie eine Union zurück, die ein Array fester Größe enthält.
– sqr163
18. Mai 2017 um 21:47 Uhr
Cs Behandlung von Arrays ist sehr anders als Java, und Sie müssen Ihr Denken entsprechend anpassen. Arrays in C sind keine erstklassigen Objekte (das heißt, ein Array-Ausdruck behält in den meisten Kontexten nicht seine “Array-Eigenschaften”). In C ist ein Ausdruck vom Typ „N-element array of T” wird implizit in einen Ausdruck vom Typ “Zeiger auf T“, außer wenn der Array-Ausdruck ein Operand von ist sizeof oder unär & -Operatoren oder wenn der Array-Ausdruck ein Zeichenfolgenliteral ist, das zum Initialisieren eines anderen Arrays in einer Deklaration verwendet wird.
Das bedeutet unter anderem, dass Sie einen Array-Ausdruck nicht an eine Funktion übergeben und empfangen lassen können als Array-Typ; Die Funktion erhält tatsächlich einen Zeigertyp:
void foo(char *a, size_t asize)
{
// do something with a
}
int bar(void)
{
char str[6] = "Hello";
foo(str, sizeof str);
}
Im Aufruf an fooder Ausdruck str wird vom Typ konvertiert char [6] zu char *weshalb der erste Parameter von foo ist deklariert char *a Anstatt von char a[6]. Im sizeof strda der Array-Ausdruck ein Operand von ist sizeof -Operator, wird er nicht in einen Zeigertyp konvertiert, sodass Sie die Anzahl der Bytes im Array (6) erhalten.
Wenn du bist Ja wirklich Interessierte können Dennis Ritchies lesen Die Entwicklung der C-Sprache um zu verstehen, woher diese Behandlung kommt.
Das Ergebnis ist, dass Funktionen keine Array-Typen zurückgeben können, was in Ordnung ist, da Array-Ausdrücke auch nicht das Ziel einer Zuweisung sein können.
Die sicherste Methode besteht darin, dass der Aufrufer das Array definiert und seine Adresse und Größe an die Funktion übergibt, die darauf schreiben soll:
In diesem Fall ist der Aufrufer dafür verantwortlich, das Array mit dem freizugeben free Bibliotheksfunktion.
Beachten Sie, dass dst im obigen Code ist ein einfacher Zeiger auf charkein Zeiger auf ein Array von char. Die Zeiger- und Array-Semantik von C ist so, dass Sie den Indexoperator anwenden können [] zu einem Ausdruck des Array-Typs oder Zeigertyp; beide src[i] und dst[i] wird auf die zugreifen i‘te Element des Arrays (obwohl nur src hat Array-Typ).
Du kann Deklarieren Sie einen Zeiger auf ein N-elementiges Array von T und etwas ähnliches tun:
Mehrere Nachteile mit den oben genannten. Zunächst einmal erwarten ältere Versionen von C SOME_SIZE eine Konstante zur Kompilierzeit zu sein, was bedeutet, dass die Funktion immer nur mit einer Array-Größe funktioniert. Zweitens müssen Sie den Zeiger dereferenzieren, bevor Sie den Index anwenden, was den Code unübersichtlich macht. Zeiger auf Arrays funktionieren besser, wenn Sie es mit mehrdimensionalen Arrays zu tun haben.
@Kundor: Was bar empfängt ist ein Zeiger, kein Array. Im Kontext einer Funktionsparameterdeklaration T a[N] und T a[] werden beide so behandelt T *a.
– Johannes Bode
14. April 2016 um 12:16 Uhr
@JohnBode: Du hast recht! Aus irgendeinem Grund dachte ich, Arrays mit fester Größe würden auf dem Stapel übergeben. Ich erinnere mich an eine Situation vor vielen Jahren, als ich herausfand, dass die Größe eines Arrays in der Parametersignatur angegeben werden musste, aber ich muss verwirrt gewesen sein.
– Nick Matteo
14. April 2016 um 13:22 Uhr
@JohnBode , im zweiten Codeteil erste Zeile:void returnArray(const char *srcArray, size_t srcSize, char *dstArray, char dstSize) Der letzte Parameter sollte in sein size_t Typ nicht char.
– Sefi
17. November 2018 um 14:36 Uhr
Ich sage nicht, dass dies die beste Lösung oder eine bevorzugte Lösung für das gegebene Problem ist. Es kann jedoch nützlich sein, sich daran zu erinnern, dass Funktionen Strukturen zurückgeben können. Obwohl Funktionen keine Arrays zurückgeben können, können Arrays in Strukturen eingeschlossen werden, und die Funktion kann die Struktur zurückgeben, wodurch sie das Array mit sich trägt. Dies funktioniert für Arrays mit fester Länge.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef
struct
{
char v[10];
} CHAR_ARRAY;
CHAR_ARRAY returnArray(CHAR_ARRAY array_in, int size)
{
CHAR_ARRAY returned;
/*
. . . methods to pull values from array, interpret them, and then create new array
*/
for (int i = 0; i < size; i++ )
returned.v[i] = array_in.v[i] + 1;
return returned; // Works!
}
int main(int argc, char * argv[])
{
CHAR_ARRAY array = {1,0,0,0,0,1,1};
char arrayCount = 7;
CHAR_ARRAY returnedArray = returnArray(array, arrayCount);
for (int i = 0; i < arrayCount; i++)
printf("%d, ", returnedArray.v[i]); //is this correctly formatted?
getchar();
return 0;
}
Ich bitte um Kommentare zu den Stärken und Schwächen dieser Technik. Ich habe mich nicht darum gekümmert.
unklar, warum dies nicht die akzeptierte Antwort ist. Die Frage war nicht, ob es möglich ist, einen Zeiger auf ein Array zurückzugeben.
– Benutzer12411795
18. Mai 2020 um 16:02 Uhr
Ist der zugewiesene Speicher CHAR_ARRAY returned auf dem haufen? Es kann sicherlich nicht auf dem Stapel (im Stapelrahmen von returnArray() Rechts?
– Minh Tran
3. Juni 2020 um 2:05 Uhr
Ja, das ist die Antwort auf meine Frage: Kann die C-Funktion ein Array zurückgeben? Ja, das kann es, und @Indinfer hat es mit der Verwendung des C-eigenen struc-Datentyps beantwortet. Und natürlich sollte es ein Array mit fester Länge sein. Dies ist C, Sie müssen von vornherein deterministisch sein, es sei denn, Sie haben Zeit, den Schmerz von Zeiger, Adresse, Malloc, Free usw. für nur eine einfache Funktionsrückgabe zu spielen. Prost.
– KokoEfraim
7. Mai 2021 um 7:05 Uhr
@MinhTran Refer godbolt.org/z/1rYocv3PT – Im Wesentlichen ring_slice wird in eine Funktion umgewandelt, die eine Adresse zum Speichern akzeptiert. Du kannst sehen main reserviert 32 Bytes auf dem Stack für ein Mem2 (sub rsp, 32) und übergibt seine Adresse per rdi zu ring_slice. Ich kenne meine Anrufkonventionen nicht wirklich, aber ich denke rdi ist normalerweise das erste Argument einer Funktion. ring_slice speichert dann seine Ergebnisse dort und gibt dieselbe Adresse zurück (mov rax, rdi).
Sie können dies mit Heap-Speicher (through malloc() Aufruf) wie andere hier gemeldete Antworten, aber Sie müssen immer den Speicher verwalten (use frei() Funktion jedes Mal, wenn Sie Ihre Funktion aufrufen). Sie können dies auch mit einem statischen Array tun:
char* returnArrayPointer()
{
static char array[SIZE];
// do something in your array here
return array;
}
Sie können es dann verwenden, ohne sich Gedanken über die Speicherverwaltung machen zu müssen.
int main()
{
char* myArray = returnArrayPointer();
/* use your array here */
/* don't worry to free memory here */
}
In diesem Beispiel müssen Sie das Schlüsselwort static in der Array-Definition verwenden, um die Array-Lebensdauer auf anwendungslang festzulegen, damit sie nach der return-Anweisung nicht zerstört wird. Auf diese Weise belegen Sie natürlich für die gesamte Anwendungslebensdauer SIZE-Bytes in Ihrem Speicher, also dimensionieren Sie ihn richtig!
Wie gut ist es, Zeiger auf den internen Speicher einer Funktion zu übergeben? Vergessen Sie Multithreading, das ist im seriellen Code schlecht.
– Benutzer426
14. November 2021 um 15:44 Uhr
In Ihrem Fall erstellen Sie ein Array auf dem Stapel, und sobald Sie den Funktionsbereich verlassen, wird das Array freigegeben. Erstellen Sie stattdessen ein dynamisch zugewiesenes Array und geben Sie einen Zeiger darauf zurück.
char * returnArray(char *arr, int size) {
char *new_arr = malloc(sizeof(char) * size);
for(int i = 0; i < size; ++i) {
new_arr[i] = arr[i];
}
return new_arr;
}
int main() {
char arr[7]= {1,0,0,0,0,1,1};
char *new_arr = returnArray(arr, 7);
// don't forget to free the memory after you're done with the array
free(new_arr);
}
Wie gut ist es, Zeiger auf den internen Speicher einer Funktion zu übergeben? Vergessen Sie Multithreading, das ist im seriellen Code schlecht.
– Benutzer426
14. November 2021 um 15:44 Uhr
Michael Dorgan
Ihre Methode gibt eine lokale Stapelvariable zurück, die schlecht fehlschlägt. Um ein Array zurückzugeben, erstellen Sie eines außerhalb der Funktion, übergeben Sie es per Adresse an die Funktion und ändern Sie es dann, oder erstellen Sie ein Array auf dem Heap und geben Sie diese Variable zurück. Beides funktioniert, aber das erste erfordert keine dynamische Speicherzuweisung, damit es richtig funktioniert.
void returnArray(int size, char *retArray)
{
// work directly with retArray or memcpy into it from elsewhere like
// memcpy(retArray, localArray, size);
}
#define ARRAY_SIZE 20
int main(void)
{
char foo[ARRAY_SIZE];
returnArray(ARRAY_SIZE, foo);
}
14256100cookie-checkZurückgeben eines Arrays mit Cyes
Hat das Rückgabearray eine bekannte Größe, wie in Ihrem Codebeispiel angegeben? Das einzige andere Problem, das ich neben den in den Antworten erwähnten Stack-Problemen sehe, ist, dass Sie nicht wissen, wie groß es ist, wenn Ihr Rückgabe-Array eine unbestimmte Größe hat, da Zeiger/Arrays in C funktionieren.
– seltsame freie Welt
25. Juli 2012 um 18:56 Uhr
Ja, ich kenne die Größe des eingehenden Arrays jederzeit. Die Größe des Eingabe- und Ausgabearrays ändert sich nicht.
– Benutzer1506919
25. Juli 2012 um 19:01 Uhr
Die Entwicklung der Sprache C* – bell-labs.com/usr/dmr/www/chist.html
– x4444
31. Dezember 2017 um 7:45 Uhr