Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does a function parameter in C always have the same memory address?

Okay, so C is pass-by-value, which means a copy of the variable is used instead of the original variable for the parameter, right? So, will that copy always have the same memory address? Consider this code:

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;
}

The output I get from this code is this:

&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

My gut feeling was "no". It is my understanding that the ptr doesn't exist outside the code block of test(). So, why is &ptr the same for all five function calls?

like image 811
instagatorTheCheese Avatar asked Oct 11 '13 02:10

instagatorTheCheese


1 Answers

&ptr is the same because ptr is a local variable within test(). Since you're calling test() five times in succession without anything intervening, it's just being given the same address on the stack every time it's called (note, this isn't in any way required by C - it's just how your machine is doing it, and how it would usually happen).

If you called a second function which then itself called test(), you would not get the same output for &ptr, since that space on the stack in which ptr was previously residing is now being used by the intervening function call.

For instance:

#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;
}

yields:

paul@local:~/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

paul@local:~/src/c/scratch$

and you can see that &ptr is different on the last call, which is made via test_test().

like image 139
Crowman Avatar answered Sep 19 '22 03:09

Crowman