int main() {
int *x;
int *y;
y = x;
printf("%p %p", &x,&y); // prints 0061FF1C 0061FF18
printf("%p %p", x, y); // prints 00400080 00400080
return 0;
}
Why don't these print the same thing? I thought using just the x and the &x would get to the same value. Also, why are the bottom ones matching if the top one's arent?
When you say y = x in this case it just means that y assumes whatever pointer value x happened to have. You never initialized x with a value, so it's just some random junk.
The address of x and y themselves is going to be different. These are two separate variables representing two separate pointers. You can assign their value to be the same, but their address remains distinct.
You're probably confusing this behaviour with:
int x = 5;
int* y = &x;
Where now y == &x but &x and &y continue to remain distinct.
As C does not have references, you really don't have situations where two independent variables are ever the same address.
Suppose you wrote this:
int main() {
int x = 5;
int y;
y = x;
printf("%p %p", &x, &y);
printf("%d %d", x, y);
}
Would you expect both lines to print the same?
With int *x; you set x as a pointer. Its value is the address of the pointed value.
So:
*x = the integer value
x = the pointer, i.e., the address of the value, address stored at x
&x = the address of the pointer. This is the address of the address.
Then y=x; copies the uninitialized address, not the value.
Related
I'm trying to understand pointers.
In the code attached I attempted figuring them out by myself but I got a bit more confused.
I do the operation *y = z and I see it make y point to the mem address allocated to z.
but why doesn't *y = *x change the mem address?
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
int *x = malloc(sizeof(int));
*x = 3;
int *z = malloc(sizeof(int));
int *y = z;
*y = *x;
printf("x: %i, %p, %p \n y: %i, %p, %p \n z: %i, %p, %p \n", *x, x, &x, *y, y, &y, *z, z, &z);
free(x);
free(z);
}
Result:
x: 3, 0x17b1260, 0x7ffeed5957f8
y: 3, 0x17b1280, 0x7ffeed5957e8
z: 3, 0x17b1280, 0x7ffeed5957f0
Thanks to anyone who answers.
Providing an initial value was added on to definitions, so its syntax is a little odd compared to an expression.
In an assignment expression, we write “thing being assigned = value”, and that is pretty straightforward.
In a simple declaration, we write “type name” to declare name to be an object of type type. In a more complicated declaration, instead of a name, we give a sort of sample expression. For example, the declaration “int *name” says *name is an int, which implies name must be a pointer to an int. The grammar for the declaration is something like “type sample-expression”, where the declaration tells us that sample-expression is of type type, and the actual type of the name declared inside the sample expression is deduced.
To add an initialization to that declaration, we append “= value”. Then we have “type sample-expression = value”. Because of the way declarations are constructed, this is not saying sample-expression is given the value value. It says the name within sample-expression is initialized with the value value.
That odd construction of declarations can be confusing to people learning C, but it is just something you have to become accustomed to.
int *x = malloc(sizeof(int)); causes x, not *x, to be initialized with malloc(sizeof(int)).
*x = 3 causes *x, not x, to be assigned with 3.
How the mechanisms of variable's scope work (local, static and global)?
I don't understand this output:
void foo1(int *z)
{
z = (int *)malloc(sizeof(int));
*z = 3;
}
void foo2(int *t)
{
*t = 3;
}
void main()
{
int y = 1;
int x = 2;
foo1(&y);
foo2(&x);
printf("%d %d", y, x);
}
output: 1 3
void foo1(int *z)
{
z = (int *)malloc(sizeof(int));
*z = 3;
}
I am not sure why you are using malloc, but *z ends up pointing to the memory address of the memory you just assigned with the malloc. So overriding the original pointer means the change isn't reflected in the original main() method.
A bit more clear:
You have a pointer * z that is pointing to the y from main(). When you use malloc it returns a pointer, so when you assign that to z, it is now pointing to a different block of memory that has nothing to do with the y from main(). You then assign this new block of memory the value of 3. Hence the original y is unchanged.
Starting in main, int y = 1; creates a local object named y and initializes it to 1.
Then int x = 2; creates a local object named x and initializes it to 2.
Then foo1(&y); calls foo1 while passing it the address of y.
In foo1(int *z), the parameter z is effectively an object local to the function foo1. As foo1 starts, z contains the address of y.
Then z = (int *)malloc(sizeof(int)); allocates memory and assigns the address of that memory to z. This changes z, so z no longer contains the address of y.
Then *z = 3; puts 3 in the place where z points, which is now the allocated memory. So the contents of the allocated memory change. y does not change because z no longer points to y, since z = (int *)malloc(sizeof(int)); changed z.
Then foo1 returns and main calls foo2(&x);, which calls foo2 while passing it the address of x.
In foo2(int *t), the parameter t is effectively an object local to the function foo2. As foo2 starts, t contains the address of x.
Then *t = 3; puts 3 in the place where t points. Since t points to x, this changes the contents of x, so now x contains 3.
Then foo2 returns.
Back inside main, printf("%d %d", y, x); prints the contents of y and x. Since y did not change, it is still 1. Since x did change, it is now 3.
Program:
int x;
int *y;
int **z;
z = (int **) malloc (sizeof(int *));
y = (int *) malloc (sizeof(int));
x = 1;
*z = &x;
*y = x;
.
.
.
Question:
What is the difference between:
*z = &x;
*y = x;
From what I understand *z points to the address of x and *y points to x, but for *y to point to x doesn't that require the address of x? I don't really understand what's going on with these two variables.
Edit:
I also want to know when do we know when a variable is allocated on the stack or on the heap?
Why is x,y, and z allocated on the stack?
Why is *y, **y, *z, **z, allocated on the heap?
Finally, does changing *z, change **z?
z is a pointer to a pointer (which will typically point to a dynamically allocated array of pointers).
y is a pointer to int. Again, more often than not it'll point to a dynamically allocated array of ints.
So, the *z = &x; is setting the pointer that z refers to to point at x. I.e., z points at a pointer, which (in turn) points to x.
*y = x; is taking the value of x and assigning it to the int pointed to by y.
For things like this, a picture is often helpful. So, our basic definitions give us this:
The we do:
z = (int **) malloc (sizeof(int *));
y = (int *) malloc (sizeof(int));
Which gives us this:
Then we do:
*z = &x;
*y = x;
Which gives us this:
In all of these, a dashed line signifies a pointer from one place to another, while the solid line indicates copying a value from one place to another.
We can then consider the long-term differences between them. For example, consider what happens if we add x=2; after all the assignments above.
In this case, *y will still equal 1, because we copied the value 1 from x to *y. **z will equal 2 though, because it's just a pointer to x -- any change in x will be reflected in **z.
This line stores the address of variable x in the memory pointed to by z:
*z = &x;
This line stores the value of x into memory pointed to by y:
*y = x;
The two assignment statements are unrelated: the second one makes a copy, while the first one does not. If you change the value of x and then retrieve **z, you will see the new value of x; however, retrieving *y would give you back the old value of x (i.e. 1).
Given:
int **a; // (double pointer)
int *b; // (pointer)
Is there any difference between *a=b and a=&b?
The first, *a = b; copies the value of the variable b to the location a points to.
The second, a = &b copies the address of b to a.
*a = b;
You're assigning the value of b to wherever a is pointing to.
a = &b;
Here you're assigning the address of b to a
& it's the operator that gets the address of a variable
* is the operator that is able to retrieve the value pointed by a pointer, the indirection as you should call this process.
so yes, this 2 statements are different.
*a = b Assigning b to the location in memory where a is pointing at
a = &b Assigning the address of b to the variable a.
I think the question here is what is the difference between the two in practice. This example illustrates this:
int x = 10;
int *y;
int *z;
y = &x;
*z = x;
printf("x: %d, *y: %d, *z: %d\n", x, *y, *z);
x = 20;
printf("x: %d, *y: %d, *z: %d\n", x, *y, *z);
The value pointed to by z does not get updated to the new x value of 20, while the value pointed to by y does.
*a=b : *a is a pointer variable which stores the address of another variable i.e. b and
a=&b : a is just a normal variable which stores address of b even though it stores address of b it would not store complete address which depends on data type
suppose this code:
main()
{
int *x;
*x = 3;
printf("%d %d %d\n", *x, &x, x);
// output 3 5448392 2293524
}
if *x is the value; &x the addres; what does mean that value of x?
*x is the value (correct)
x is the address of the value. EDIT In your case, this address is uninitialized, so it is not pointing anywhere in particular (thanks Keith Nicholas for mentioning this).
&x is the address of the [pointer that should contain the] address of the value.
(it's worth pointing out that your program may crash :)
Adr value expression
----------------------------------------------
5448392 2293524 &x address of x
2293524 3 x place where you assigned 3
x gives you the address in memory where value of *x, i.e. 3 is located. &x gives the address where value of x, i.e. 2293524 is located.
It is the address that x contains. Having been declared as a pointer, x stores an address, while &x is in a sense a pointer to a pointer.
EDIT: So I wasn't as precise as perhaps I should have been. &x is strictly speaking not a pointer to a pointer. It is the address of a pointer. In the following line of code, y is a pointer to a pointer:
int **y = &x;
x is a pointer to an int, its not an int itself, its not the address of an int, its a pointer.
a pointer contains an address of an int.
so, a missing step you have ( your program doesn't point x to anything! very dangerous)
int y = 5;
int *x;
x = &y // put the memory location of y into the pointer
if you now print the contents of the pointer...
printf("%d\n", x); // prints out the memory location of y;
now to get to the value of what your pointer points to ( at the moment, y)
printf("%p\n", *x); // prints out 5;
now, just like y has a memory location, x also has a location in memory
so &x is where the pointer 'x' is in memory
x is uninitialized so it points to nowhere and dereferencing it with * is undefined behaviour.
The following would be a more correct (and useful) program
main()
{
int x; //declare an int variable
int *xp; //declare a pointer to an int variable
xp = &x;
*xp = 3;
printf("%d %d %d %d %d\n", x, &x, xp, *xp, &xp);
}
x is a value, xp and &xp point to that value, *xp can be used to access and change the value and &xp is a pointer to that pointer...
&x is the address of the pointer object.
The value of the pointer is the address of an int.
Also, you shouldn't assign to *x as in your example: x doesn't point anywhere valid.
x and &x values are of pointer types so you should use p conversion specifier to print their values.
printf("%d %p %p\n", *x, (void *) &x, (void *) x);
Don't forget to cast to void * otherwise the call to printfis undefined behavior. (p conversion specifier requires an argument of type void *).
int *x;
int y = 0;
x = &y;
*x = 3;
x is a pointer to int. *x is an int and its value is 3. And &x is a pointer to a pointer to int. Note that your pointer has to point to a valid object object (like above) otherwise it has an invalid value.