2016-04-22 26 views
5

Na przykład:Gdzie przechowywane są dane const?

W pliku demo.c,

#inlcude<stdio.h> 
int a = 5; 
int main(){ 
    int b=5; 
    int c=a; 
    printf("%d", b+c); 
    return 0; 
} 

Dla int a = 5, kompilator przełożyć to na coś takiego sklepu 0x5 adresem pamięci wirtualnej, na przykład, Ox0000000f w const obszarze tak, że dla int c = a, jest to przetłumaczone na coś takiego jak movl 0x0000000f %eax?

Następnie dla int b = 5, numer 5 nie jest umieszczany w obszarze stałym, lecz jest bezpośrednio tłumaczony na bezpośredni w instrukcji montażu, takiej jak mov $0x5 %ebx.

+5

Ponieważ program nie daje żadnych widocznych efektów, kompilator może całkowicie nie przechowywać niczego. ([Przykład] (https://godbolt.org/g/5DAwmj)) –

+1

Pomijając specyfikę twojego pytania, dane const są ogólnie przechowywane we własnej sekcji, np. ".rodata" (ro tylko do odczytu). W przypadku typów POD, takich jak 'int', wartości pamięci są bezpośrednio zapisywane w tej sekcji pliku wykonywalnego, którą system operacyjny ładuje w pamięci podczas uruchamiania. W takim przypadku nie ma instrukcji, aby zainicjować pamięć - zaczyna się od właściwej wartości w ten sposób! Globalne (niestałe) dane zazwyczaj pojawiają się również w swojej sekcji, np. ".data" lub ".bss" (.bss jest domyślnie inicjalizowane do zera podczas uruchamiania programu, ponownie przez system operacyjny). – Cameron

+2

Szczegóły zależą w dużym stopniu od twojej platformy. Niektóre ISA pozwalają na bezpośrednie wartości w instrukcjach, więc wartości mogą być częścią niektórych instrukcji; inne wartości mogą po prostu być częścią obrazu programu i są określane przez adres. Inne wartości (np. Zero) mogą w ogóle nie wymagać przechowywania, a zamiast tego są dostarczane przez specjalną mechanikę ładowania. –

Odpowiedz

1

To zależy. Program posiada kilka stałych:

int a = 5; 

jest to „statyczna” inicjalizacji (który pojawia się, gdy tekst programu i dane są ładowane przed biegania). Wartość jest przechowywana w pamięci zarezerwowanej przez a, która znajduje się w "sekcji programu" do odczytu i zapisu. Jeśli coś zmieni się na a, wartość 5 zostanie utracona.

int b=5; 

Jest to zmienna lokalna z ograniczonym zakresem (tylko przez main()). Magazyn może być rejestrem CPU lub lokalizacją na stosie. Instrukcje generowane dla większości architektur będzie to wartość 5 w instrukcji jako „natychmiastowego danych”, na przykład x86:

mov eax, 5 

Zdolność do instrukcji do przechowywania dowolnych stałych jest ograniczona. Małe stałe są obsługiwane przez większość instrukcji CPU. "Duże" stałe zwykle nie są obsługiwane bezpośrednio. W takim przypadku kompilator zapamięta stałą w pamięci i załaduje ją zamiast niej. Na przykład,

 .psect rodata 
k1  dd  3141592653 
     .psect code 
     mov  eax k1 

rodzina ARM ma potężny projekt dla ładowania większość stałych bezpośrednio: dowolny 8-bitowa wartość stałą można obracać każdą parzystą liczbę razy. Zobacz this strona 2-25.

Jeden nie-jak-to oczywiste, ale zupełnie inna rzecz jest w sprawozdaniu:

printf("%d", b+c); 

Ciąg %d jest przez nowoczesne semantyki C, stałej tablicy trzech char. Większość współczesnych implementacji będzie przechowywać je w pamięci tylko do odczytu, więc próby jej zmiany spowodują SEGFAULT, który jest niskim poziomem błędu procesora, który zazwyczaj powoduje natychmiastowe przerwanie programu.

 .psect rodata 
s1  db  '%', 'd', 0 
     .psect code 
     mov  eax s1 
     push eax 
+0

, który znajduje się w "sekcji programu" do odczytu i zapisu, więc znajduje się w sekcji .data? –

+0

@Gab: Użyłem semantyki z asemblera Intela z lat osiemdziesiątych. Nie było nic o nazwie ".data". Zamiast tego były psekty o nazwie 'rodata',' rwdata' i 'stack'. Zostaną one zgrupowane w "segmencie" o nazwie "dane". – wallyk

+0

W moim przykładzie, dla 'int b = 5; ', możemy powiedzieć, że" dane "5 są zapisywane bezpośrednio w instrukcji jako bezpośrednia liczba, prawda? Czy to "5" pojawia się w segmencie kodu? –

1

W programie OP a jest "zainicjowanym" "globalnym". Oczekuję, że zostanie on umieszczony w zainicjalizowanej części segmentu danych. Zobacz https://en.wikipedia.org/wiki/File:Program_memory_layout.pdf, http://www.cs.uleth.ca/~holzmann/C/system/memorylayout.gif (od more info on Memory layout of an executable program (process)). O lokalizacji a decyduje duet kompilator-linker.

Z drugiej strony, jako zmienne automatyczne (stos), b i c oczekuje się w segmencie stosu.

Mówiąc to, kompilator/linker może przeprowadzić dowolną optymalizację, o ile zaobserwowane zachowanie nie zostanie naruszone (What exactly is the "as-if" rule?). Na przykład, jeśli a nigdy nie zostanie przywołany, może zostać całkowicie zoptymalizowany.

Powiązane problemy