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).
Related
In the following code I would like to understand better what is happening with int *z = malloc(sizeof(int);
To me that creates a pointer to an int. Then *z gets the sum of the value that x points to (2) and the value that y points to (4).
Now *z = 6. Does that mean *z does not point to anything? It just stores an int? I thought *z was a pointer and a pointer is an address? Thank you for any help understanding.
int *add(int *x, int *y)
{
int *z = malloc(sizeof(int));
*z = (*x) + (*y);
return z;
}
int main(void)
{
int a = 2;
int b = 4;
int *ptr = add(&a, &b);
printf("sum = %i\n", *ptr);
}
Now *z = 6. Does that mean *z does not point to anything? It just stores an int? I thought *z was a pointer and a pointer is an address? Thank you for any help understanding.
You are correct with *z = 6 however you are wrong with how this happens.
z is a pointer and so it point somewhere into the memory. Earlier in your program, with int *z = malloc(sizeof(int)); you have allocated a space the z points to.
Then when you did *z = (*x) + (*y); you've basically put the result of the addition into that allocated space.
z still points to that space (because it is a pointer). *z is called dereferencing and has a meaning of reaching directly for the value the pointer points to.
In other words: the 6 is stored in a place the z points to and *z is a way to grab that value.
*z = 6 assigns 6 to the location pointed at by ptr. That's what a pointer does, it points to things, but in order to put a value at where it's pointing as opposed to changing the pointer you need to de-reference with the * operator.1
Imagine your memory as, conceptually, a number of bytes each of which has a number. A pointer to an int represents a particular location in memory which is presumed to hold an int, or 4 bytes worth of data.
*z = 6 means "put an integer value of 6 in the memory location described by z", which translates into machine instructions that are largely the same.
z absolutely does not "store an int", it stores a location. That location may exist, or may be NULL, or may be invalid. There's no guarantees unless you've checked your code carefully to ensure the pointer is valid. That's your responsibility as a programmer.
That's also why pointers can be tricky and frustrating. They introduce indirection in your code.
1 In C pointers are also largely interchangeable with arrays so you can do z[0] = 6, though as z only points to a single int, any index other than 0 is invalid.
int *z = malloc(sizeof(int));
this will envoke a system call for allocating one integer on the heap. z is the address of this integer return from malloc (if malloc fails to allocate z will be null)
z is a pointer to buffer allocated on the heap (if malloc success). in your case this buffer hold one integer so its a pointer to this integer.
see malloc description in man pages. malloc_man_pages
*z = (*x) + (*y);
you are right. you are assigning the value that sets in the address x and the value that sets in the address y to the place that z points to.
you dont check the return vale from malloc and this is a very bad thing. always check if malloc successd! see below. maybe you need to check the pointers that you get in x and y ?! (thats up to you, but i recommend to check).
int* add(int *x, int *y)
{
int *z = NULL;
if(x && y)
{
z = malloc(sizeof(int));
if(z)
{
*z = (*x) + (*y);
}
}
return z;
}
I am very new to C and currently having some trouble with pointers and I am not sure if my logic is correct on this question clarification would be great.
Is the second expression legal? Why or Why not? What does it mean?
int** x = ....;
... **x ...
This is all the question gives and I came up with the following answer (I think its in the ballpark)
The int** x will initialize a pointer x to whatever address/value that is after the equal sign.
**x ... will dereference the pointer to a value/variable
The question link that was proposed in the edit was just showing the difference between int* p and int *p which is nothing what i asked i understand this already.
int *x is a pointer to int. int** y defines y as a pointer to pointer to int, so it points to a pointer, and the latter points to an int. Example:
int n = 42;
int* x = &n; // points to n
int** y = &x; // points to x, which points to n
In this case y is a pointer to pointer. First indirection *y gives you a pointer (in this case x), then the second indirection dereferences the pointer x, so **y equals 42.
Using typedefs makes everything looks simpler, and makes you realize that pointers are themselves variables as any other variables, the only exception being that they store addresses instead of numbers(values):
typedef int* pINT;
int n = 42;
pINT x = &n;
pINT* y = &x; // y is a pointer to a type pINT, i.e. pointer to pointer to int
If you use double * you are telling the compiler you want a pointer pointing to another pointer:
int x = 4;
int *pointer = &x;
int **pointer_pointer = &pointer;
printf("%d\n",**pointer_pointer); // This should print the 4
#include <stdlib.h>
int main(void)
{
int* x;
int* y;
x = malloc(sizeof(int));
*x = 42;
*y = 13;
y = x;
return 0;
}
Where is the Error in which line and why.. ? Can't I assign pointer to another pointer. Yes nothing is being printed out in this .. Actually its my homework question...
You need to allocate memory for y before assigning value to it.
y = malloc(sizeof(int));
*y = 13
The error is here: *y = 13; The problem is that y has not been previously assigned (i.e. an undefined behavior).
Switching
*y = 13;
y = x;
to
y = x;
*y = 13;
fixes the problem. Obviously, the memory leak of malloc(sizeof(int)) still remains.
y is a wild pointer, you are assigning 13 to nothing. You need to malloc() it, too.
Either use malloc like
y = malloc(sizeof(int));
*y = 13;
or make y a stack-variable like
int y = 0;
...
y = *x; //copy value from x to y by dereferencing x
When you use pointers,you have to understand one thing : You are not actually allocating memory in the stack,you just create a pointer to something.That something can be anything but we don't really care. We just have to initialize it and we do that by making it point to something.
There are two ways,the first one is to make it point to a stack variable and the second to make it point to place in the stack,that you allocated using malloc().
The first way:
int x; //you create a stack variable
int *ptr; //you create a type int pointer
ptr=&x; //you make ptr point to the adress where 'x' is
The second way:
int *ptr; //you create a type int pointer
*ptr=malloc(sizeof(int)); you allocate memory for one int
The problem with you code above is that you haven't allocated memory for int *y and yet you try to save a number there.
Your code could be written like that
#include <stdlib.h>
int main(void)
{
int* x;
int* y;
x = malloc(sizeof(int));
y = malloc(sizeof(int));
//now both pointers point to a place in memory so you can actually save data on them
*x = 42;
*y = 13;
y = x;
return 0;
}
The problem of cource here is that when you make y point to x ,you lose the place y was pointing and you leave non usable allocating place in the memory.So before making y point to x you could use free().
*y=13;
free(y);
y=x;
I am translating C code to another language. I am confused about pointers.
Say I have this code. The function foo, calls function bob, and they are both pointers.
double
*foo(double *x, double *init, double *a){
double *y = (double*)malloc(5*sizeof(double));
double *z = (double*)malloc(5*sizeof(double));
double *sum, *update;
sum = (double*)bob(y, z) //<---Q1: why y and z don't need stars in front of them?
//I thought they are pointers?
for (i<0; i<5; i++){
z[i]=y[i] //Q2: howcome it's ok to assign y to z?
} //aren't they pointer?(i.e.hold memory address)
}
double
*bob(*arg1, *arg2){
something...
}
So,
1) Why y and z don't need stars in front of them, isn't y and z just address?
2) Why sum doesn't have a star, I thought sum is declared as a pointer.
3) Why it's ok to assign y to z?
I've learned these, but they've soooo long, could someone give me a hint?
double
*foo(double *x, double *init, double *a){
// x is a pointer to a double, init is a pointer to a double, a is a pointer to a double
// foo is a function returning a pointer to a double
// and taking three pointers to doubles as arguments
double *y = (double*)malloc(5*sizeof(double));
// y is a pointer to a double. It is assigned a pointer returned by malloc.
// That pointer returned by malloc points to memory space for 5 doubles.
double *z = (double*)malloc(5*sizeof(double));
// z is a pointer to a double. It is assigned a pointer returned by malloc.
// That pointer returned by malloc points to memory space for 5 doubles.
double *sum, *update;
// sum and update are pointers to doubles
sum = (double*)bob(y, z) //<---Q1: why y and z don't need stars in front of them?
//I thought they are pointers?
// sum (whose type is pointer to double)
// is assigned a pointer to double returned by bob
for (i<0; i<5; i++){
y[i] = z[i] //and are z and y pointers?!?!
// y[i] === *(y+i)
// (y + i) points to the i-th element in the space previously allocated by malloc
// *(y + i) dereferences that pointer
// equivalently, y[i] accesses the i-th element from an array
}
if(sum<0)
z=y //Q2: howcome it's ok to assign y to z?
//aren't they pointer?(i.e.hold memory address)
// after the assignment, z contains the same address as y (points to the same memory)
}
double
*bob(*arg1, *arg2){
something...
}
Values y and z don't need stars because adding a star dereferences them, and you want to pass the pointer not the value.
Again, you want the pointer and not the value. Although from the code it appears you actually DO want the value, so there probably should be a star there.
You can assign a pointer to another pointer, this means change the address that the pointer points to. So when y=z, y now points where z points.
They don't need a star because you do not dereference them, but pass as pointers.
You can compare pointer, but that's probably not what you want.
Assigning pointers is okay, note, though, that it's not the same as copying values.
Ans for Q1: You are passing y and z to another function which take in pointers as arguments, why would you pass the value of the pointer?
Ans2: They are pointers and you are assigning one to another
Basic pointer notions:
double a = 42.0; // a is a double
double b; // b is a double
double *x; // x is a pointer to double
x = &a; // x is the pointer, we store the address of a in pointer x
b = *x; // *x is the pointee (a double), we store the value pointed by x in b
// now b value is 42.0
With regard to 2) and why z[i] = y[i] is acceptable, I think it best to point you to this page which describes arrays and pointers in some detail, especially 2.1 through 2.8. What's happening in that particular expression (not necessarily in order) is start at location y, fetch the pointer, add i to the pointer, then fetch the value pointed to at that location. Start at z, fetch the pointer, add i to the pointer, and assign the value (y[i]) to that location.
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.