pointer als zweites Argument anstatt Zeiger zurückzugeben?

8

Ich habe bemerkt, dass es in C ein gängiges Idiom ist, einen un malloc ed-Zeiger als zweites Argument zu akzeptieren, anstatt einen Zeiger zurückzugeben. Beispiel:

%Vor%

Anstelle von

%Vor%

Was sind die Vor- und / oder Nachteile beider Ansätze?

Danke!

BEARBEITEN Vielen Dank für Ihre Antworten. Die Beweggründe für die Wahl 1 sind mir jetzt sehr klar (und ich sollte darauf hinweisen, dass das Zeigerargument für die Wahl 1 im Gegensatz zu dem ursprünglich gedachten malloc sein sollte).

    
Tyler 26.03.2010, 02:13
quelle

7 Antworten

16

Das Akzeptieren eines Zeigers (den der Aufrufer für malloc'ing verantwortlich ist oder nicht) in den Speicher, der ausgefüllt werden soll, bietet erhebliche Vorteile in der Flexibilität gegenüber dem Zurückgeben eines Zeigers ( notwendigerweise malloc'ed). Insbesondere wenn der Aufrufer weiß, dass er nur innerhalb einer bestimmten Funktion zurückgegebene Daten verwenden muss, kann er die Adresse einer dem Stack zugeordneten Struktur oder eines Arrays übergeben; Wenn es weiß, dass es keine Reentrancy benötigt, kann es die Adresse eines static struct oder array übergeben - in jedem Fall wird ein malloc / free-Paar gespeichert, und solche Einsparungen steigen auf! -)

    
Alex Martelli 26.03.2010, 02:19
quelle
5

Das macht nicht viel Sinn. Zeiger in C werden wie andere Objekte wertmäßig übergeben - der Unterschied liegt im Wert. Bei Zeigern ist der Wert die Speicheradresse, die an die Funktion übergeben wird. Sie duplizieren den Wert jedoch immer noch, und wenn Sie malloc ändern, ändern Sie den Wert des Zeigers in Ihrer Funktion und nicht den Wert außen.

%Vor%

Es gibt drei Möglichkeiten, dies zu vermeiden. Der erste ist, wie Sie bereits erwähnt haben, den neuen Zeiger aus der Funktion zurückzugeben. Die zweite besteht darin, einen Zeiger auf den Zeiger zu nehmen und ihn dabei als Referenz zu übergeben:

%Vor%

Das dritte ist einfach malloc n außerhalb des Funktionsaufrufs:

%Vor%     
Samir Talwar 26.03.2010 02:20
quelle
2

Normalerweise bevorzuge ich das Empfangen von Zeigern (Eigenschaft initialisiert) als Funktionsargumente im Gegensatz zum Zurückgeben eines Zeigers zu einem Speicherbereich, der innerhalb der Funktion malloc'ed wurde. Mit diesem Ansatz machen Sie explizit, dass die Verantwortung für die Speicherverwaltung auf der Benutzerseite liegt.

Das Zurückgeben von Zeigern führt normalerweise zu Speicherlecks, da es leichter ist, Ihre Zeiger zu vergessen (), wenn Sie sie nicht malloc () 'ed gemacht haben.

    
mgv 26.03.2010 02:29
quelle
1

Normalerweise mache ich keine feste Wahl, lege es sauber in seine eigene Bibliothek und biete das Beste aus beiden Welten.

%Vor%

Für jeden malloc sollte es ein free geben, also sollte für jede init ein Begriff sein und für jedes create sollte es einen destroy geben. Wenn Ihre Objekte komplexer werden, werden Sie feststellen, dass Sie beginnen, sie zu verschachteln. Einige Objekte auf höherer Ebene können eine node_t-Liste für die interne Datenverwaltung verwenden. Bevor Sie dieses Objekt freigeben, muss die Liste zuerst freigegeben werden. _init und _term kümmern sich darum, dieses Implementierungsdetail vollständig zu verstecken.

Es kann Entscheidungen über weitere Details geben, z. Destroy kann einen node_t ** n nehmen und nach dem Freigeben von * n auf NULL setzen.

    
Secure 26.03.2010 06:52
quelle
0

persönlich Ich möchte Daten mit Reference oder Zeigerparametern zurückgeben und die Funktion return für die Rückgabe von Fehlercodes verwenden.

    
SteelBytes 26.03.2010 02:16
quelle
0

1) Da Samir darauf hingewiesen hat, dass der Code falsch ist, wird der Zeiger als Wert übergeben, Sie brauchen **

2) Die Funktion ist im Wesentlichen ein Konstruktor, daher ist es sinnvoll, den Speicher zu belegen und die Datenstruktur zu initialisieren. Sauberer C-Code ist fast immer objektorientiert wie bei Konstruktoren und Destruktoren.

3) Ihre Funktion ist ungültig, sollte aber int zurückgeben, damit Fehler zurückgegeben werden können. Es wird mindestens 2, wahrscheinlich 3 mögliche Fehlerbedingungen geben: malloc kann fehlschlagen, Typargument kann ungültig sein und möglicherweise kann der Wert außerhalb des Bereichs liegen.

    
MK. 26.03.2010 03:36
quelle
0

Ein Problem, das in diesem Artikel nicht behandelt wird, ist die Frage, wie Sie sich auf den malloc'ed buffer innerhalb der Funktion beziehen, die ihn zuweist und vermutlich etwas darin speichert, bevor es die Kontrolle an seinen Aufrufer zurückgibt.

>

In dem Fall, der mich auf diese Seite gebracht hat, habe ich eine Funktion, die einen Zeiger übergibt, der die Adresse eines Arrays von HOTKEY_STATE-Strukturen empfängt. Der Prototyp erklärt das Argument wie folgt.

%Vor%

Der Rückgabewert ruintNKeys ist die Anzahl der Elemente im Array, die von der Routine vor der Zuweisung des Puffers bestimmt werden. Anstatt malloc () direkt zu verwenden, habe ich jedoch wie folgt Calloc verwendet.

%Vor%

Nachdem ich überprüft habe, dass plplpHotKeyStates nicht mehr null ist, habe ich eine lokale Zeigervariable, hkHotKeyStates, wie folgt definiert:

%Vor%

Wenn Sie diese Variable mit einer Ganzzahl ohne Vorzeichen für einen Index verwenden, füllt der Code die Strukturen mit dem einfachen Elementoperator (.), wie unten gezeigt.

%Vor%

Wenn das Array vollständig gefüllt ist, gibt es ruintNKeys zurück, und der Aufrufer hat alles, was er benötigt, um das Array zu verarbeiten, entweder auf herkömmliche Weise, unter Verwendung des Referenzoperators (- & gt;) oder mit der gleichen Technik wie I in der Funktion verwendet, um direkten Zugriff auf das Array zu erhalten.

    
David Gray 31.03.2013 01:16
quelle

Tags und Links