Wie gebe ich mehrere Werte von einer Funktion in C zurück?
Lesezeit: 8 Minuten
Tony Stark
Wenn ich eine Funktion habe, die ein Ergebnis erzeugt int und ein Ergebnis stringwie gebe ich sie beide von einer Funktion zurück?
Soweit ich das beurteilen kann, kann ich nur eine Sache zurückgeben, die durch den Typ bestimmt wird, der dem Funktionsnamen vorangestellt ist.
Durch string meinst du “Ich benutze C++ und das ist die std::string Klasse” oder “Ich verwende C und dies ist eine char * Zeiger bzw char[] Anordnung.”
– Chris Lutz
12. April 2010 um 6:15 Uhr
Nun, in meinem speziellen Fall waren es zwei Ints: eine für die „Punktzahl“ dessen, was ich verglichen habe, und eine für den „Index“, wo diese maximale Punktzahl gefunden wurde. Ich wollte hier nur für den allgemeineren Fall ein String-Beispiel verwenden
– Tony Stark
12. April 2010 um 6:22 Uhr
Übergeben Sie die Zeichenfolge als Referenz und geben Sie das int zurück. Schnellste Weg. Keine Strukturen erforderlich.
– Stefan Steiger
12. April 2010 um 7:34 Uhr
Tut eine Funktion, die 2 Ergebnisse zurückgibt, nicht mehr als eine Sache? Was würde Onkel Bob sagen?
– Duncan
12. April 2010 um 7:37 Uhr
Travis Göckel
Ich weiß nicht, was du bist string ist, aber ich gehe davon aus, dass es seinen eigenen Speicher verwaltet.
Sie haben zwei Lösungen:
1: Rückkehr a struct die alle Typen enthält, die Sie benötigen.
void getPair(int* a, string* b) {
// Check that these are not pointing to NULL
assert(a);
assert(b);
*a = 1;
*b = getString();
}
void foo() {
int a, b;
getPair(&a, &b);
}
Welche Sie wählen, hängt weitgehend von Ihren persönlichen Vorlieben ab, welche Semantik Ihnen besser gefällt.
Ich denke, es hängt mehr davon ab, wie verwandt die Rückgabewerte sind. Wenn int ein Fehlercode und der String ein Ergebnis ist, dann sollten diese nicht in einer Struktur zusammengefügt werden. Das ist einfach albern. In diesem Fall würde ich das int zurückgeben und den String als a übergeben char * und ein size_t für die Länge, es sei denn, es ist absolut wichtig, dass die Funktion ihre eigene Zeichenfolge zuweist und / oder zurückgibt NULL.
– Chris Lutz
12. April 2010 um 6:14 Uhr
@Chris Ich stimme dir vollkommen zu, aber ich habe keine Ahnung von der Verwendungssemantik der Variablen, die er benötigt.
– Travis Gockel
12. April 2010 um 6:16 Uhr
Guter Punkt Chris. Eine andere Sache, die meiner Meinung nach erwähnenswert ist, ist Wert vs. Referenz. Wenn ich mich nicht irre, bedeutet die Rückgabe der Struktur wie im Beispiel gezeigt, dass bei der Rückgabe eine Kopie erstellt wird, ist das richtig? (Ich bin ein bisschen wackelig in C) Während die andere Methode Pass-by-Reference verwendet und daher nicht mehr Speicher zuweisen muss. Natürlich könnte die Struktur über einen Zeiger zurückgegeben werden und denselben Nutzen haben, oder? (Stellen Sie sicher, dass Sie den Speicher richtig zuweisen und all das natürlich)
– RTHarston
9. Februar 2019 um 6:58 Uhr
@BobVicktor: C hat überhaupt keine Referenzsemantik (das ist exklusiv für C ++), also ist alles ein Wert. Die Zwei-Zeiger-Lösung (Nr. 2) besteht darin, Kopien der Zeiger an eine Funktion zu übergeben, die getPair dann Dereferenzen. Je nachdem, was Sie tun (OP hat nie geklärt, ob dies tatsächlich eine C-Frage ist), kann die Zuweisung ein Problem darstellen, befindet sich jedoch normalerweise nicht im C++-Land (Rückgabewertoptimierung speichert all dies) und im C-Land, Daten Kopien passieren normalerweise explizit (via strncpy oder Wasauchimmer).
– Travis Gockel
12. Februar 2019 um 0:41 Uhr
@TravisGockel Danke für die Korrektur. Ich bezog mich auf die Tatsache, dass Zeiger verwendet werden, also werden die Werte nicht kopiert, sondern nur das geteilt, was bereits zugewiesen wurde. Aber Sie haben Recht, wenn Sie sagen, dass dies in C nicht richtig als Pass-by-Reference bezeichnet wird. Und danke auch für die anderen großartigen Wissensnuggets. Ich liebe es, diese kleinen Dinge über Sprachen zu lernen. 🙂
– RTHarston
22. Oktober 2019 um 21:51 Uhr
codaddict
Option 1: Deklarieren Sie eine Struktur mit einem int und einem String und geben Sie eine Strukturvariable zurück.
Option 2: Sie können einen der beiden per Zeiger übergeben und Änderungen am aktuellen Parameter durch den Zeiger vornehmen und den anderen wie gewohnt zurückgeben:
int fun(char **param) {
int bar;
...
strcpy(*param,"....");
return bar;
}
Option 3: Ähnlich wie bei Option 2. Sie können sowohl per Pointer übergeben als auch nichts von der Funktion zurückgeben:
void fun(char **param1,int *param2) {
strcpy(*param1,"....");
*param2 = /* some calculated value */
}
Bei Option 2 sollten Sie auch die Länge der Zeichenfolge übergeben. int fun(char *param, size_t len)
– Chris Lutz
12. April 2010 um 6:16 Uhr
Das hängt jetzt davon ab, was die Funktion macht. Wenn wir wissen, welche Art von Ergebnis die Funktion in das char-Array schreibt, könnten wir einfach genug Platz dafür zuweisen und es an die Funktion übergeben. Keine Notwendigkeit, die Länge zu übergeben. Etwas Ähnliches wie wir verwenden strcpy zum Beispiel.
– codaddict
12. April 2010 um 6:31 Uhr
Jess Beder
Da einer Ihrer Ergebnistypen ein String ist (und Sie C und nicht C++ verwenden), empfehle ich, Zeiger als Ausgabeparameter zu übergeben. Verwenden:
void foo(int *a, char *s, int size);
und nenne es so:
int a;
char *s = (char *)malloc(100); /* I never know how much to allocate :) */
foo(&a, s, 100);
Generell sollte man die Zuordnung lieber in der vornehmen Berufung Funktion, nicht innerhalb der Funktion selbst, damit Sie möglichst offen für unterschiedliche Allokationsstrategien sein können.
zs2020
Erstellen Sie eine Struktur und legen Sie zwei Werte darin fest und geben Sie die Strukturvariable zurück.
struct result {
int a;
char *string;
}
Sie müssen Platz für die zuweisen char * in deinem Programm.
Zwei unterschiedliche Ansätze:
Übergeben Sie Ihre Rückgabewerte per Zeiger und ändern Sie sie innerhalb der Funktion. Sie deklarieren Ihre Funktion als void, aber sie kehrt über die als Zeiger übergebenen Werte zurück.
Definieren Sie eine Struktur, die Ihre Rückgabewerte aggregiert.
Ich denke, dass #1 etwas offensichtlicher ist, was vor sich geht, obwohl es langweilig werden kann, wenn Sie zu viele Rückgabewerte haben. In diesem Fall funktioniert Option Nr. 2 ziemlich gut, obwohl die Erstellung spezieller Strukturen für diesen Zweck mit einigem mentalen Aufwand verbunden ist.
C hat keine Referenzen ;-), obwohl seit dem verwendeten Poster stringes könnte sicher sein, C ++ anzunehmen …
– Travis Gockel
12. April 2010 um 6:11 Uhr
Das ganz vergessen! Ich habe meine Antwort geändert, um Zeiger zu verwenden, aber ich war eindeutig zu lange im C++-Land. 🙂
– James Thompson
12. April 2010 um 6:55 Uhr
Bloodlee
Verwenden Sie Zeiger als Funktionsparameter. Verwenden Sie sie dann, um mehrere Werte zurückzugeben.
C hat keine Referenzen ;-), obwohl seit dem verwendeten Poster stringes könnte sicher sein, C ++ anzunehmen …
– Travis Gockel
12. April 2010 um 6:11 Uhr
Das ganz vergessen! Ich habe meine Antwort geändert, um Zeiger zu verwenden, aber ich war eindeutig zu lange im C++-Land. 🙂
– James Thompson
12. April 2010 um 6:55 Uhr
Ein Ansatz ist die Verwendung von Makros. Platzieren Sie dies in einer Header-Datei multitype.h
Dadurch ist es möglich, bis zu vier Variablen aus einer Funktion zurückzugeben und bis zu vier Variablen zuzuweisen. Als Beispiel können Sie sie wie folgt verwenden:
multitype (int,float,double) fun() {
int a = 55;
float b = 3.9;
double c = 24.15;
RETURN (a,b,c);
}
int main(int argc, char *argv[]) {
int x;
float y;
double z;
let (x,y,z) = fun();
printf("(%d, %f, %g\n)", x, y, z);
return 0;
}
Das ist, was es druckt:
(55, 3.9, 24.15)
Die Lösung ist möglicherweise nicht so portabel, da sie C99 oder höher für variadische Makros und for-Statement-Variablendeklarationen erfordert. Aber ich denke, es war interessant genug, hier zu posten. Ein weiteres Problem ist, dass der Compiler Sie nicht warnt, wenn Sie ihnen die falschen Werte zuweisen, also müssen Sie vorsichtig sein.
Weitere Beispiele und eine Stack-basierte Version des Codes mit Unions sind unter my verfügbar Github-Repository.
Ein größeres Portabilitätsproblem ist die Nicht-Standard-Funktion __typeof__
– MM
19. November 2017 um 23:02 Uhr
Anstelle von typeof könnten Sie wahrscheinlich sizeof verwenden. Holen Sie sich die Größe der Rückgabewerte und weisen Sie ein Array zu, das groß genug ist, um sie alle zu speichern. Dann kannst du es zurückgeben.
– Klaus. S
21. November 2017 um 11:57 Uhr
14213100cookie-checkWie gebe ich mehrere Werte von einer Funktion in C zurück?yes
Durch
string
meinst du “Ich benutze C++ und das ist diestd::string
Klasse” oder “Ich verwende C und dies ist einechar *
Zeiger bzwchar[]
Anordnung.”– Chris Lutz
12. April 2010 um 6:15 Uhr
Nun, in meinem speziellen Fall waren es zwei Ints: eine für die „Punktzahl“ dessen, was ich verglichen habe, und eine für den „Index“, wo diese maximale Punktzahl gefunden wurde. Ich wollte hier nur für den allgemeineren Fall ein String-Beispiel verwenden
– Tony Stark
12. April 2010 um 6:22 Uhr
Übergeben Sie die Zeichenfolge als Referenz und geben Sie das int zurück. Schnellste Weg. Keine Strukturen erforderlich.
– Stefan Steiger
12. April 2010 um 7:34 Uhr
Tut eine Funktion, die 2 Ergebnisse zurückgibt, nicht mehr als eine Sache? Was würde Onkel Bob sagen?
– Duncan
12. April 2010 um 7:37 Uhr