2013-10-11 11 views
6

OK, więc C jest wartością typu pass-by-value, co oznacza, że ​​zamiast zmiennej oryginalnej użyto kopii zmiennej, prawda? Czy ta kopia będzie miała zawsze ten sam adres pamięci? Rozważmy następujący kod:Czy parametr funkcji w C ma zawsze ten sam adres pamięci?

void test(int *ptr) { 
    printf("&ptr: %p\n", &ptr); 
    printf("ptr: %p\n", ptr); 
    printf("*ptr: %d\n\n", *ptr); 
} 

int main() { 
    int a = 1, b = 2, c = 3, d = 4, e = 5; 
    test(&a); 
    test(&b); 
    test(&c); 
    test(&d); 
    test(&e); 

    return 0; 
} 

Wyjście mam z tego kodu jest to:

&ptr: 0x7fff70536728 
ptr: 0x7fff7053674c 
*ptr: 1 

&ptr: 0x7fff70536728 
ptr: 0x7fff70536750 
*ptr: 2 

&ptr: 0x7fff70536728 
ptr: 0x7fff70536754 
*ptr: 3 

&ptr: 0x7fff70536728 
ptr: 0x7fff70536758 
*ptr: 4 

&ptr: 0x7fff70536728 
ptr: 0x7fff7053675c 
*ptr: 5 

Moje przeczucie było „nie”. Rozumiem, że ptr nie istnieje poza blokiem kodu test(). Dlaczego więc &ptr jest takie samo dla wszystkich pięciu wywołań funkcji?

+4

Nie można zagwarantować, że będzie taki sam. Obserwujesz nieokreślone zachowanie. (Możesz zobaczyć zmianę adresu, jeśli wywołasz go z innej funkcji oprócz głównej.) –

+0

i może nie wykazywać takiego zachowania w ogóle, nawet bez interweniującego wywołania funkcji. w zależności od implementacji na konkretnej maszynie. –

+0

@AndyzSmith także w zależności od tego, jak kompilator zdecyduje się go zaimplementować. :) – jmstoker

Odpowiedz

6

&ptr jest taki sam, ponieważ ptr jest zmienną lokalną w zakresie test(). Ponieważ pięć razy z rzędu dzwonisz pod numer test(), ale nic nie interweniuje, po prostu otrzymuje ten sam adres na stosie za każdym razem, gdy jest wywoływany (uwaga, to nie jest w żaden sposób wymagane przez C - to tylko jak twoja maszyna jest robienie tego i jak to zwykle bywa).

Jeśli nazywa drugą funkcję, która następnie sama nazwie test(), nie dostanie taką samą moc na &ptr, od tego miejsca na stosie, w którym ptr wcześniej zamieszkałych jest obecnie używany przez interweniujące wywołania funkcji.

Na przykład:

#include <stdio.h> 

void test(int *ptr) { 
    printf("&ptr: %p\n", (void *) &ptr); 
    printf("ptr: %p\n", (void *) ptr); 
    printf("*ptr: %d\n\n", *ptr); 
} 

void test_test(void) { 
    int a = 1; 
    test(&a); 
} 

int main() { 
    int a = 1, b = 2, c = 3, d = 4, e = 5; 

    test(&a); 
    test(&b); 
    test(&c); 
    test(&d); 
    test(&e); 
    test_test(); 

    return 0; 
} 

plony:

[email protected]:~/src/c/scratch$ ./ptrtest 
&ptr: 0x7fff39f79068 
ptr: 0x7fff39f7909c 
*ptr: 1 

&ptr: 0x7fff39f79068 
ptr: 0x7fff39f79098 
*ptr: 2 

&ptr: 0x7fff39f79068 
ptr: 0x7fff39f79094 
*ptr: 3 

&ptr: 0x7fff39f79068 
ptr: 0x7fff39f79090 
*ptr: 4 

&ptr: 0x7fff39f79068 
ptr: 0x7fff39f7908c 
*ptr: 5 

&ptr: 0x7fff39f79048 
ptr: 0x7fff39f7906c 
*ptr: 1 

[email protected]:~/src/c/scratch$ 

i widać, że &ptr różni się od ostatniej rozmowy, która jest wykonana poprzez test_test().

+0

Ah w porządku, teraz ma sens. – instagatorTheCheese

Powiązane problemy