2009-11-06 6 views
10

Mam pytanie o następującym kodzie C:Kiedy jest miejsce na stosie przydzielone dla zmiennych lokalnych?

void my_function() 
{ 
    int i1; 
    int j1; 

    // Do something... 

    if (check_something()) 
    { 
     int i2; 
     int j2; 

     // Do something else... 
    } 

    // Do some more stuff... 
} 

Czy istnieją jakieś zagwarantować, kiedy przestrzeń stosu jest przydzielona/przydziałów dla i2 i J2, czy też zależy od kompilatora? Spodziewam się, że wskaźnik stosu zostanie skorygowany, gdy i2 i j2 wejdą w zakres i skorygują kopie zapasowe, gdy wyjdą poza zasięg, ale wtedy myślę, że niektóre kompilatory mogą po prostu "zoptymalizować" całą rzecz i uwzględnić zmienne w zakresie zagnieżdżonym, gdy funkcja jest najpierw wprowadzana.

Wiem, że mogę spojrzeć na kod generowany przez mój kompilator, ale zastanawiałem się, czy implementację można pozostawić kompilatorowi.

Dzięki!

+5

Weź również pod uwagę, że zmienne mogą być przypisane do rejestrów ... – unwind

Odpowiedz

6

Kompilator może robić co chce, tak długo jak semantyka języka są zastrzeżone. Innymi słowy, i2 imożna powiązać z miejscami w pamięci, zanim wykonanie osiągnie punkt wejścia ich bloku i może być nieograniczony w dowolnym momencie, o ile nie ma to wpływu na semantykę kodu.

8

Nie ma żadnych gwarancji.

Różne flagi optymalizacji prawdopodobnie spowodują różne metody zapisywania zmiennych.

Kompilator może nawet wprowadzić 1 lub więcej zmiennych, które w ogóle nie używają stosu i przechowywać je w rejestrach przez cały czas wykonywania funkcji.

+0

+! bez gwarancji. –

4

Jak rozumiem, nawet nie można uzyskać żadnej gwarancji, że zmienne są przydzielane na stosie, mogą być przechowywane w rejestrach.

Co naprawdę może wpłynąć tutaj:

  • Advice kompilator umieszczenia zmiennej zarejestrować za pomocą rejestr słowa kluczowego.

  • Pomoc kompilator z lokalizowaniu zmienny zakres przesuwając deklarację jako późnym miejscu, jak można:

 
    int f(void) 
    { 
     /* var1 and var2 probably use the same place for storage. */ 
     { 
      int var1; 
      /* ... do something */ 
     } 

     { 
      int var2; 
      /* ... do something */ 
     } 
    } 


  • nawet przy określonym inicjalizacji opóźnienia zakres:
 
{ 
    int i; /* Yes, you must declare it at the begin of block. 

    /* Do something... */ 

    i = START_VALUE; 
    /* But you need it only here and below... */ 
} 
0

jeśli "check_something()" można łatwo ocenić na 0, cały blok zostanie zoptymalizowany przy użyciu odpowiednio wysokiego poziomu optymalizacji. Tak, zależy to od kompilatora. Ogólnie rzecz biorąc, jeśli sprawdzasz wartość zwracaną przez wywołanie funkcji, nie zostanie ona zoptymalizowana. Najlepszym sposobem podejścia do tego problemu byłoby skompilowanie go i faktycznie przyjrzenie się dezasemblacji pliku w celu sprawdzenia, co tak naprawdę dzieje się w rzeczywistości.

3

Jeśli zmienne zostaną umieszczone na stosie, przestrzeń stosu jest przydzielana na początku funkcji przed pierwszą instrukcją w funkcji.Wskaźnik stosu zostanie przesunięty w górę (lub w dół) całkowitej liczby bajtów w celu zapisania wszystkich zmiennych lokalnych.