Reputation: 4270
So I have two functions:
int main(int argc, char *argv[]) {
int i = 1;
printf("Pointer of i in main: %p\n", &i);
printf("Value of i in main %d\n", i);
change_pointer(&i);
printf("Value of i in main %d\n", i); // doesn't change is equal to 1
printf("Pointer of i in main: %p\n", &i); // doesn't change
return 0;
}
void change_pointer(int *i) {
printf("Pointer of i in change_pointer: %p \n", i); // same as main
int j = 2;
printf("Pointer of j in change_pointer: %p\n", &j);
i = &j;
printf("Pointer of i in change_pointer after i = &j: %p\n", &i);
// different to &j memory location it is 4 bytes after it
printf("Value of i in change_pointer %d\n", *i); // is equal to 2
}
My questions are:
1) What is happening when I assign the address of i
to the address of j
, why is it exactly 4 bytes after it?
2) Is the complier changing the address of the variable of i
so that i
and j
won't have the same address?
3) If so why is the complier doing this and not alerting me to it?
4) How does *i
have a value at that address is NULL, does the complier copy the value of j
over?
Upvotes: 0
Views: 919
Reputation: 16540
in C, all parameters are passed by value. so the passed parameter in the function change_value()
is a copy, sitting on the stack. when you directly assign to 'i' via: i = &j;
all that is being changed is the copy of the address on the stack. to set the caller's 'i' variable use: '*i = j;' Since &i is pointing to some location on the callers' stack, that address cannot really change, but the contents of 'i' in the callers' stack can be changed. again, via: *i = j;
Upvotes: 0
Reputation: 16017
(Note: You actually assign the address of j to i.) Then you compare the address of j and the address of i. They are adjacent in memory because they lie next to each other on the stack. (Google "stack layout explained" to learn more about how the stack works and what it is used for.)
For simple use cases it is fair to imagine that the compiler translates each variable name to an offset to an address. Each name stands for a different offset. I.e. i
may mean 0, j
may be 4.The offset is applied to the current stack frame for automatic variables and function arguments and to some constant address (the beginning of some segment of the program) for external or static variables. It is guranteed that different objects (e.g. the objects denoted by i and j) have different locations, i.e. addresses in memory. That's one of the most basic and most important-to-get-right jobs of a compiler. Don't get confused: You have two distinct variables here which are both named i
: One in main()
, one in change_pointer()
. They denote two distinct objects which consequently reside in distinct locations in memory. The i which is an argument to change_pointer()
is a pointer which has an address and contains an address. That may seem confusing.
If you output i
instead of &i
in change_pointer()
you get the value contained in i
, which is the address of j
.
The compiler is not changing any addresses. More elaborate runtimes with garbage collection change locations (and hence addresses) of objects at run time (notably most Java VMs and the CLR); but they have to keep track of all references to them and change those, atomically, at the same time. The more rudimentary runtimes of C and C++ usually can't do that.
I do not understand the question. Which i
are you refering to? Where do you see a NULL?
Upvotes: 0
Reputation: 16607
Is the complier changing the address of the variable of i so that i and j won't have the same address?
Compiler doesn't change address , they both already have different address as they are different variables.
printf("Pointer of i in change_pointer after i = &j: %p\n", &i);
// different to &j memory location it is 4 bytes after it
Ofcourse it will be different than that of j
as &i
will give in that function address of pointer i
.
In you function change_pointer
-
*i
has value 2
not because value of j
is copied but of fact that pointer i
points to address of j
and value 2
is at that address.
In change_pointer
if you write like this -
*i=j; // instead of i=&j;
Then value of i
in main
will change to 2
.
Upvotes: 0
Reputation: 3767
1) What is happening when I assign the address of i to the address of j, why is it exactly 4 bytes after it?
Well i in your function is now referring to address of local j instead of referring to address of i in main.
2) Is the complier changing the address of the variable of i so that i and j won't have the same address?
nope, you are probably looking at two different values &j and &i, where as the correct values should be i and &j.
3) If so why is the complier doing this and not alerting me to it ?
Question number 2 is not correct hence not answering this.
4) How does *i have a value at that address is NULL, does the complier copy the value of j over?
Value that i is refering to is j which is 2, I can't see NULL anywhere
Upvotes: 0
Reputation: 148890
All is perfectly normal. C always pass variables by value. When you call change_pointer(&i);
you pass the address of i, meaning that through that pointer you could now change the value of i.
But in change_pointer
, i
is a local variable initially containing the address of main i
. When you change its value to have it pointing to j
, you only change the local pointer. So nothing is changed on return.
You could change the value of i
that way:
int main(int argc, char *argv[]) {
int i = 1;
printf("Pointer of i in main: %p\n", &i);
printf("Value of i in main %d\n", i);
change_value(&i);
printf("Value of i in main %d\n", i); // is now 2
printf("Pointer of i in main: %p\n", &i); // doesn't change
return 0;
}
void change_value(int *i) {
printf("Pointer to i in change_pointer: %p \n", i); // same as main
int j = 2;
printf("Pointer to j in change_pointer: %p\n", &j);
*i = j;
printf("Value of i in change_pointer %d\n", *i); // is equal to 2
}
Upvotes: 1