2013-05-15 4 views
8

stworzyłem prosty program:Zmienna deklaracja i ich adresy pamięci w C

#include <stdio.h> 

int main() 
{ 
    int s1; 
    int s2; 
    int s3; 

    int *p1, *p2, *p3; 

    p1 = &s1; 
    p2 = &s2; 
    p3 = &s3; 

    printf("%d\n%d\n%d", p1, p2, p3); 
} 

Ilekroć uruchomić ten program, drukuje adresy pamięci wskaźników p1, p2 i p3 i ciekawe jest to, że te wartości różnią się od siebie o 12. Chcę poznać przyczynę tego. Dlaczego adresy różnią się o 12?

Uwaga: Tak się dzieje za każdym razem Wykonuję program.

wyjściowa:

enter image description here


Przetestowałem ten sam program w wielu typów zmiennych, wyniki i dostaje to ..

Kiedy zmienne są typu char. enter image description here


gdy zmienne typu long enter image description here


Kiedy zadeklarować int tablicę, rozmiar każdej tablicy jest 1. enter image description here


gdy wielkość drugiego deklarowanej tablicy wynosi 2, otrzymuje dodatkowe 4 bajty przesunięcia. enter image description here

+1

Dlaczego nie użyć specyfikatora formatu przeznaczonego do drukowania wskaźników, a jeszcze lepiej "std :: cout"? A dlaczego nie użyć ważnego podpisu dla 'main'? – chris

+0

Spojrzenie na wygenerowany kod (w debuggerze lub deasemblatorze) prawdopodobnie pomoże ci oświecić cię. – cHao

+6

Jaki jest kompilator i platforma? – Steve

Odpowiedz

5

Jestem dość pewien, że jest to przypadek "kompilatora umieszcza dodatkowe rzeczy, aby wykryć, kiedy piszesz w miejscach, w które nie powinieneś". Micrsoft lubi to robić, aby mógł wykryć, kiedy twój kod robi złe rzeczy. Spróbuj czegoś takiego:

void func() 
{ 
    int x = 18; 
    int *px = &x; 
    px[1] = 4711; 
    cout << "px = " << px << " x = " << x << " px[1] = " << px[1] << endl; 
} 

i zobaczyć, czy kompilator nie „wykryć” że ten kod robi złe rzeczy ... Jeśli tak, to dlatego, że to put „wyściółkę” między x i i p, i sprawdza, czy funkcja zwraca, że ​​obszary "dopełnienia" nie zostały dotknięte.

+0

'gcc -g -O0 -Wall -fstack-protector-all -Wstack-protector op_code.c -o a.out' ma przesunięcie o 4 bajty jakie ma okno ochrony, którego nie ma w gcc? – 0x90

+0

@ 0x90 (lub powinienem zadzwonić do Ciebie NOP?): Jeden z komentarzy mówi, że OP używa Visual Studio 2008, więc nie używając gcc. –

+0

Wiem, dlaczego dlatego pytam, co kompilator microsoft wie zrobić GCC nie? :) – 0x90

15

Zgaduję, że jest to kompilacja debugowania. Próbowałem tego programu zbudowanego z Visual Studio 2010. Podczas debugowania istnieje 12 bajtowa różnica między adresami. W trybie zwolnienia występuje 4-bajtowa różnica (sizeof(int)).

W kompilacjach debugujących kompilator MSVC dodaje dodatkowe dane, aby wykryć przepełnienie bufora i użycie niezainicjowanej pamięci. Jeśli umieścisz punkt przerwania na swojej instrukcji printf i przejrzysz pamięć wskazaną przez p1, powinieneś zobaczyć w pamięci .

Istnieje wiele różnych wartości magicznych inicjowanych w pamięci. cccccccc wskazuje niezaimitowane przestrzeń stosu. Aby uzyskać bardziej szczegółową listę, zobacz odpowiedź na to pytanie: In Visual Studio C++, what are the memory allocation representations?