int *p;
p = (int*) malloc(n*sizeof(int));
I know there is a similar post but I have not gotten the point. So here in the example, I have a pointer that is being assigned a new pointer with malloc. So now the address of the pointer has changed? Is it a new address with the exact space that we have given with malloc? Can someone explain what we are doing in an easy way? I am getting confused.
CodePudding user response:
There are two ways to think about this — the "high level" way and the "low level" way.
High level: I like to use labeled boxes to represent variables and other objects. If I say
int i = 5;
then I have an int-shaped box, named i
, containing the value 5:
-------
i: | 5 |
-------
If I then say
int *p = &i;
then I have a pointer-shaped box, named p
, containing a pointer that points at variable i
:
-------
i: | 5 |
-------
^
|
--|----
p: / * /
-------
If I then say
p = malloc(5 * sizeof(int));
and if malloc
succeeds, then p
now contains a pointer pointing at some new, unnamed memory which malloc
gave me:
-------
p: / * /
----|--
|
v
-------
| |
-------
| |
-------
| |
-------
| |
-------
| |
-------
That's the high-level way. For the low-level way, I'm going to think about pointers not as those pretty little arrows, but as actual, numeric memory addresses.
I typed in this program:
#include <stdio.h>
int main()
{
int i = 5;
printf("i: %p: %d\n", &i, i);
int *p = &i;
printf("p: %p: %p: %d\n", &p, p, *p);
}
When I ran it on my computer, I got this output:
i: 0x7ffee74ed9cc: 5
p: 0x7ffee74ed9c0: 0x7ffee74ed9cc: 5
So I can draw a different version of the box-and-arrow picture, showing actual addresses:
-----
0x7ffee74ed9cc: | 5 |
-----
--------------
0x7ffee74ed9c0: | 7ffee74ed9cc |
--------------
Now suppose I do
p = malloc(5 * sizeof(int));
p[0] = 11;
p[1] = 22;
p[2] = 33;
p[3] = 44;
p[4] = 55;
printf("p: %p: %p: %d %d %d\n", &p, p, *p, p[1], p[2]);
Now it prints
p: 0x7ffee74ed9c0: 0x7fbd11500000: 11 22 33
so I can draw this picture:
--------------
0x7ffee74ed9c0: | 7fbd11500000 |
--------------
------
0x7fbd11500000: | 11 |
------
0x7fbd11500004: | 22 |
------
0x7fbd11500008: | 33 |
------
0x7fbd1150000c: | 44 |
------
0x7fbd11500010: | 55 |
------
CodePudding user response:
p
is the pointer to int.
The assignment does not change its address only the value it holds. So &p
will always be the same through its lifetime.
Casting to pointer to pointer does not change anything only the type of the pointer returned by the malloc
There is no need to cast the result of malloc
. It is considered bad practice as it silences the warnings, leading to hard to find errors.
You should always assign pointers of the same type (void *
) is the only exception.
It is a good practice to use objects instead of types in sizeof
.
p = malloc(n*sizeof(*p));
If you change the type of p
you do not need to change it in all sizeof
s in your code. It also often leads to hard to find errors if you forget to change one.