2016-08-09 8 views
3

Ich verwende derzeit eine Routine String_concat(char *str1, char *str2), die, wie der Name schon sagt, zwei Strings verkettet. Zu diesem Zweck reserviert diese Routine dynamisch Speicher auf dem Heap (über malloc()). Da die zurückgegebene Zeichenfolge jedoch nur in der aufrufenden Routine verwendet wird, denke ich darüber nach, Speicher auf dem Stack direkt zuzuweisen (über alloca()). Daher würde ich String_concat() durch etwas wie String_concat2(char* str1, char* str2, char* dest) ersetzen, das den Zielpuffer (bereits auf dem Stack zugewiesen) übernehmen würde) als Argument. Also meine Frage ist: Ist es in Ordnung für String_concat2() in den Stapel seiner aufrufenden Routine schreiben, oder muss ich erzwingen inline über __attribute__((always_inline))?Ist es für ein Unterprogramm sicher, in den Stapel seiner aufrufenden Routine zu schreiben?

+0

C11 Normentwurf n1570: * 6.2.4 Speicherdauern o f objects 2 Die Lebensdauer eines Objekts ist der Teil der Programmausführung, in dem der Speicher garantiert reserviert ist. Ein Objekt existiert, hat eine konstante Adresse, 33) und behält seinen letzten gespeicherten Wert während seiner gesamten Lebensdauer bei. 34) Wenn ein Objekt außerhalb seiner Lebensdauer bezeichnet wird, ist das Verhalten nicht definiert. Der Wert eines Zeigers wird unbestimmt, wenn das Objekt, auf das er zeigt (oder gerade erst), das Ende seiner Lebensdauer erreicht. * – EOF

+2

Später im Projekt, wenn Sie die Funktion verwenden möchten, um Zeichenfolgen zu erzeugen, die nur * nicht * verwendet werden in der Anruffunktion, was dann? Dies scheint ein Fall vorzeitiger Optimierung zu sein, der einfach nicht benötigt wird und nicht sehr zukunftssicher ist. –

+0

Möchten Sie dies aus Leistungsgründen tun? Weil das wie eine wirklich starke Kopplung zwischen den Routinen aussieht, und ich denke, das ist fast immer eine schlechte Sache ... –

Antwort

5

Es gibt kein Problem für eine Funktion in den Stapelrahmen seiner aufrufenden Funktion zu schreiben.

Zum Beispiel:

void foo(int *ptr) { 
    *ptr = 7; 
} 

void bar(void) { 
    int value; 
    foo(&value); 
} 

In dem obigen Code, foo Funktion zu einer Stelle schreibt, die in dem Stapelrahmen der bar Funktion ist, die es erfordert.

+0

Ha offensichtlich, Warum habe ich nicht daran gedacht? Vielen Dank ! –

3

Eine aufgerufene Routine kann immer Werte in ihrem Aufrufer ändern. Aber es sei denn, Sie möchten die Assemblersprache verwenden, um zu simulieren, was der Compiler tut, kann Speicherplatz im Aufrufer-Stack nicht zuordnen, da seine eigenen Variablen bereits da sind.

Wenn Sie ein Array an Ihre Anrufer zurückkommen müssen, die nur zwei tragbare Wege sind:

  • Rufenen ordnet mit malloc Speicher und geben Sie die Adresse seiner Anrufer - der Anrufer später den Block Speicher frei
  • Anrufer vorge Ordnen Speicher und einen Puffer an den Angerufenen passieren - die Angerufene füllt nur den Puffer und kümmert sich nicht, wo es zugeordnet ist, nicht, ob es überhaupt zugeordnet ist (möglicherweise statischen oder dynamischen Speicher sein)
Verwandte Themen