Ich bin relativ neu in C und brauche Hilfe bei Methoden, die mit Arrays umgehen. Ich komme aus der Java-Programmierung und bin es gewohnt, sagen int [] method()
zu können, um ein Array zurückzugeben. Ich habe jedoch herausgefunden, dass Sie mit C Zeiger für Arrays verwenden müssen, wenn Sie sie zurückgeben. Als neuer Programmierer verstehe ich das ü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 der Methode (nennen wir sie returnArray) ein Array zur Verfügung stellen. Es wird ein neues Array aus dem vorherigen Array erstellt und ein Zeiger darauf zurückgegeben. Ich brauche nur etwas Hilfe, wie man damit anfängt und wie man den Zeiger liest, sobald er aus dem Array gesendet wird. Jede Hilfe, die dies erklärt, ist willkommen.
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 dies noch nicht getestet, da mein C-Compiler derzeit nicht funktioniert, aber ich möchte dies herausfinden
Antworten:
Sie können keine Arrays von Funktionen in C zurückgeben. Sie können (sollten) dies auch nicht tun:
returned
wird mit automatischer Speicherdauer erstellt und Verweise darauf werden ungültig, sobald sie ihren deklarierenden Bereich verlassen, dh wenn die Funktion zurückkehrt.Sie müssen den Speicher innerhalb der Funktion dynamisch zuweisen oder einen vom Aufrufer bereitgestellten vorab zugewiesenen Puffer füllen.
Option 1:
Ordnen Sie den Speicher innerhalb der Funktion dynamisch zu (Anrufer, der für die Freigabe verantwortlich ist
ret
)Nennen Sie es so:
Option 2:
Füllen Sie einen vom Aufrufer bereitgestellten vorab zugewiesenen Puffer (der Anrufer weist
buf
die Funktion zu und übergibt sie an sie).Und nenne es so:
quelle
C der Behandlung von Arrays ist sehr verschieden von Java, und Sie werden Ihr Denken entsprechend anpassen müssen. Arrays in C sind keine erstklassigen Objekte (dh ein Array-Ausdruck behält in den meisten Kontexten nicht seine "Array-Ness" bei). In C wird ein Ausdruck vom Typ "N-Element-Array von
T
" implizit in einen Ausdruck vom Typ "Zeiger aufT
" konvertiert ("Zerfall") , es sei denn, der Array-Ausdruck ist ein Operand dersizeof
oder unären&
Operatoren oder wenn der Der Array-Ausdruck ist ein String-Literal, mit dem ein anderes Array in einer Deklaration initialisiert wird.Dies bedeutet unter anderem, dass Sie einen Array-Ausdruck nicht an eine Funktion übergeben und als Array-Typ empfangen lassen können . Die Funktion erhält tatsächlich einen Zeigertyp:
Beim Aufruf von
foo
wird der Ausdruckstr
vom Typ konvertiertchar [6]
inchar *
, weshalb der erste Parameter von anstelle vonfoo
deklariertchar *a
wirdchar a[6]
. Insizeof str
Da die Array - Ausdruck ein Operand ist , dersizeof
Bediener, es ist nicht auf einen Zeigertyp umgewandelt, so dass man die Anzahl der Bytes in dem Feld (6) erhalten.Wenn Sie wirklich interessiert sind, können Sie Dennis Ritchies Die Entwicklung der C-Sprache lesen, 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:
Eine andere Methode besteht darin, dass die Funktion das Array dynamisch zuweist und den Zeiger und die Größe zurückgibt:
In diesem Fall ist der Aufrufer dafür verantwortlich, die Zuordnung des Arrays zur
free
Bibliotheksfunktion aufzuheben.Beachten Sie, dass
dst
der obige Code ein einfacherchar
Zeiger auf ein Array von istchar
. Die Zeiger- und Array-Semantik von C ist so, dass Sie den Indexoperator[]
entweder auf einen Ausdruck vom Typ Array oder vom Zeigertyp anwenden können . beidesrc[i]
unddst[i]
greifen auf dasi
'th Element des Arrays zu (obwohl nursrc
den Array-Typ hat).Sie können einen Zeiger auf ein N-Element-Array von deklarieren
T
und etwas Ähnliches tun:Mehrere Nachteile mit den oben genannten. Erstens erwarten ältere Versionen von C
SOME_SIZE
eine Konstante für die Kompilierungszeit, was bedeutet, dass die Funktion immer nur mit einer Arraygröße funktioniert. Zweitens müssen Sie den Zeiger dereferenzieren, bevor Sie den Index anwenden, der den Code überfüllt. Zeiger auf Arrays funktionieren besser, wenn Sie mit mehrdimensionalen Arrays arbeiten.quelle
bar
erhält, ist ein Zeiger, kein Array. Im Rahmen einer Funktion Parameterdeklaration,T a[N]
undT a[]
sind beide so behandelt , alsT *a
.void returnArray(const char *srcArray, size_t srcSize, char *dstArray, char dstSize)
letzte Parameter sollte vomsize_t
Typ nicht seinchar
.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 das Array mitgeführt wird. Dies funktioniert für Arrays mit fester Länge.
Ich lade Sie ein, Kommentare zu den Stärken und Schwächen dieser Technik abzugeben. Ich habe mich nicht darum gekümmert.
quelle
CHAR_ARRAY returned
auf dem Heap reserviert ? Es kann sicher nicht das auf dem Stapel sein (im Stapelrahmen vonreturnArray()
rechts?Wie wäre es mit dieser köstlich bösen Implementierung?
array.h
Haupt c
quelle
struct
als Array-Container / Objekt zurückzugeben. Stellen Sie es sich wie einen C ++ std :: vector vor. Der Präprozessor würde dieint
Version davon auf erweiternstruct intArray { int* contents; int size; };
.In Ihrem Fall erstellen Sie ein Array auf dem Stapel. Sobald Sie den Funktionsumfang verlassen, wird die Zuordnung des Arrays aufgehoben. Erstellen Sie stattdessen ein dynamisch zugewiesenes Array und geben Sie einen Zeiger darauf zurück.
quelle
new
In C gibt es keinen Operator. Das ist C ++.sizeof(char)
ist garantiert1
, also können Sie in diesem Fall das Bit von fallen lassenmalloc
.&arr
. Du willstarr
ein seinchar *
und es weitergeben mitarr
.Sie können dies wie andere hier gemeldete Antworten mithilfe des Heap-Speichers (durch Aufruf von malloc () ) tun , aber Sie müssen den Speicher immer verwalten (verwenden Sie die Funktion free () jedes Mal, wenn Sie Ihre Funktion aufrufen). Sie können dies auch mit einem statischen Array tun:
Sie können es dann verwenden, ohne sich um die Speicherverwaltung kümmern zu müssen.
In diesem Beispiel müssen Sie das statische Schlüsselwort in der Array-Definition verwenden, um die Lebensdauer des Arrays auf anwendungslang festzulegen, damit es nach der return-Anweisung nicht zerstört wird. Auf diese Weise belegen Sie natürlich GRÖSSE Bytes in Ihrem Speicher für die gesamte Anwendungslebensdauer. Passen Sie die Größe also richtig an!
quelle
Ihre Methode gibt eine lokale Stapelvariable zurück, die fehlerhaft ausfällt. Um ein Array zurückzugeben, erstellen Sie eines außerhalb der Funktion, übergeben Sie es als Adresse an die Funktion, ändern Sie es dann oder erstellen Sie ein Array auf dem Heap und geben Sie diese Variable zurück. Beide funktionieren, aber die erste erfordert keine dynamische Speicherzuweisung, damit sie ordnungsgemäß funktioniert.
quelle
Sie können folgenden Code verwenden:
Wenn Sie dies tun, sollte der Speicher später freigegeben werden, indem Sie die Adresse an free übergeben.
Es gibt andere Möglichkeiten. Eine Routine kann einen Zeiger auf ein Array (oder einen Teil eines Arrays) zurückgeben, das Teil einer vorhandenen Struktur ist. Der Aufrufer übergibt möglicherweise ein Array, und die Routine schreibt lediglich in das Array, anstatt Speicherplatz für ein neues Array zuzuweisen.
quelle