Werden in c / c ++ Blockbereichsvariablen nur gestapelt, wenn der Block ausgeführt wird?

8

Angenommen, dies:

void func()
{
 ...
 if( blah )
 {
  int x;
 }
 ...
}  

Ist der Platz für xden Stapel sofort reserviert, wenn er funceingegeben wird, oder nur, wenn der Block tatsächlich ausgeführt wird?
Oder ist es die Wahl des Compilers?
Verhalten sich C und C ++ dabei gleich?

Petruza
quelle
1
Da die Implementierung definiert ist, sollten Sie sich einige Beispiele für Code ansehen, der von verschiedenen Compilern generiert wurde, um eine Idee zu haben. In diesem Vortrag von Microsoft spricht der Präsentator kurz über das, was er "Stack Packing" auf dem VisualC ++ - Compiler nennt. Dies ist wahrscheinlich eine Optimierung, um nur den minimal benötigten Stack-Speicherplatz für jede Funktion zuzuweisen.
Glampert

Antworten:

12

Wer hat gesagt, dass der Compiler keinen Platz reserviert (könnte nur registriert werden).

Dies ist völlig undefiniert.
Sie können nur sagen, dass auf it ( x) nur innerhalb des inneren Blocks zugegriffen werden kann.

Wie der Compiler Speicher zuweist (auf einem Stapel, falls vorhanden), liegt vollständig beim Compiler (da der Speicherbereich möglicherweise für mehrere Objekte wiederverwendet wird (wenn der Compiler nachweisen kann, dass sich ihre Lebensdauer nicht überschneidet)).

Ist der Platz für x sofort auf dem Stapel reserviert, wenn func eingegeben wird?

Unbestimmt.

oder nur wenn der block tatsächlich ausgeführt wird?

Unbestimmt.
Wenn es sich xjedoch um ein Klassenobjekt handelt, wird der Konstruktor nur ausgeführt, wenn der Block eingegeben wird.

Oder ist es die Wahl des Compilers?

Der Compiler weist möglicherweise nicht einmal Speicher zu.

Verhalten sich C und C ++ dabei gleich?

Ja

Martin York
quelle
3
Ich würde davon ausgehen, dass eine zu große Sorge darüber, wie der Compiler damit umgeht, für die meisten Anwendungen eine vorzeitige Optimierung wäre.
TheShrike
4

Nun, es ist wirklich die Wahl des Compilers, aber was ich beobachtet habe, ist, dass der Compiler beim Kompilieren ohne Optimierungen (was wir normalerweise tun, um unseren Code debuggen zu können) dazu neigt, die Dinge ziemlich klar zu machen geschnittene, deterministische und zuverlässige Mode:

  • Der Compiler ist nicht optimieren entfernt alle lokalen Variablen. (Außer vielleicht Variablen, die explizit als definiert sind register, aber das muss überprüft werden.)

  • Der Stapelspeicherplatz für alle lokalen Variablen, unabhängig davon, wie sie verschachtelt sind, wird bei der Eingabe der Funktion sofort reserviert.

  • Der Stapelspeicher wird nicht über separate verschachtelte Bereiche hinweg wiederverwendet. Dies bedeutet, dass void f(){ { int x; } { int y; } }Platz für zwei intVariablen zugewiesen wird. Der zugewiesene Speicherplatz xwird nicht wiederverwendet y.

Wenn Sie Optimierungen aktivieren, ist natürlich alles wahr, was Loki Astari in der akzeptierten Antwort geschrieben hat.

Mike Nakis
quelle