Understanding Pointer to Pointer Logic in C - c

I came across this code and was a bit confused on exactly what's going on here:
int **p;
p = malloc(sizeof(int *));
*p = malloc(sizeof(int));
**p = 10;
printf("%d\n",**p);
First of, p is a pointer to a pointer but it doesn't point to anything else, so why would we have to malloc twice here? Also in the first malloc call, why does one not need to have two pointer values around the p:
for instance:
**p = malloc(sizeof(int *));
instead of :
p = malloc(sizeof(int *));
I understand that the next line deference's the pointer and stores the value 10 in it, and then prints it. However I don't really get the previous lines, or at least why they're done in that frame of mind.
I'm used to seeing double pointers in this mindset:
int main(void) {
int *ptr;
int **ptr_ptr;
ptr = malloc(sizeof(int));
*ptr = 5;
ptr_ptr = &ptr;
printf("%d\n",**ptr_ptr); /*prints 5*/
free(ptr);
return 0;
}
As the double pointer actually points to something here. Any help with the first bit of code would be much appreciated.

As int **p is a pointer to pointer, it will hold the location or address of an int* type of pointer. But one must first allocate enough memory for the int* which will be stored at the location pointed by p. This line does this job, it initializes p:
p = malloc(sizeof(int *));
Now, that int*'s location is known, one must allocate memory to store an acutal int at the memory pointed by *p which is our int* pointer. So another malloc() call is needed to initialize the int* type pointer.
*p = malloc(sizeof(int));
When all of it is done, an integer can be assigned to **p, which is the int pointed by *p:
**p = 10;

After the two mallocs, the variable p contains a pointer to a malloc-allocated pointer, which in turn contains a pointer to a malloc-allocated integer:
+---+ +---+ +----+
p: | ----> | ----> | 10 |
+---+ +---+ +----+

Related

What does *p mean when **p is already declared

Code
short **p = (short **)malloc(sizeof(short *));
*p = malloc(sizeof(short));
**p = 10;
printf("**p = %d", **p);
Output
**p = 10
In this code, a multiple pointer **p is declared and *p is used without any declaration(maybe it's by **p).
What does *p mean in my case? Sorry for very simple question.
I saw C standard and stack overflow, but I couldn't find out something.
For any array or pointer p and index i, the expression p[i] is exactly equal to *(p + i) (where * is the unary dereference operator, the result of it on a pointer is the value that the pointer is pointing to).
So if we have p[0] that's then exactly equal to *(p + 0), which is equal to *(p) which is equal to *p. Going backwards from that, *p is equal to p[0].
So
*p = malloc(sizeof(short));
is equal to
p[0] = malloc(sizeof(short));
And
**p = 10;
is equal to
p[0][0] = 10;
(**p is equal to *(*(p + 0) + 0) which is equal to *(p[0] + 0) which is then equal to p[0][0])
It's important to note that the asterisk * can mean different things in different contexts.
It can be used when declaring a variable, and then it means "declare as pointer":
int *p; // Declare p as a pointer to an int value
It can be used to dereference a pointer, to get the value the pointer is pointing to:
*p = 0; // Equal to p[0] = 0
And it can be used as the multiplication operator:
r = a * b; // Multiply the values in a and b, store the resulting value in r
short **p = (short **)malloc(sizeof(short *));
This line declares a pointer to a pointer p. Additionally the value of p is set to the return value from malloc. It is equivalent to
short **p;
p = (short **)malloc(sizeof(short *));
The second line
*p = malloc(sizeof(short));
Here *p is the value of p. *p is of type pointer. *p is set to the return value of malloc. It is equivalent to
p[0] = malloc(sizeof(short));
The third line
**p = 10;
**p is the value of the value of p. It is of type short. It is equivalent to
p[0][0] = 10
In effect what the code above does is to allocate a 2D array of short, then allocate memory for the first row, and then set the element p[0][0] to 10.
As a general comment on your code, you should not use typecast in malloc. See Do I cast the result of malloc?
What does *p mean when **p is already declared?
short **p = (short **)malloc(sizeof(short *));
(better written as)
short **p = malloc (sizeof *p);
Declares the pointer-to-pointer-to short p and allocates storage for a signle pointer with malloc and assigns the beginning address for that block of memory to p. See: In C, there is no need to cast the return of malloc, it is unnecessary. See: Do I cast the result of malloc?
*p = malloc(sizeof(short));
(equivalent to)
p[0] = malloc (sizeof *p[0]);
Allocates storage for a single short and assigns the starting address for that block of memory to p[0].
**p = 10;
(equivalent to)
*p[0] = 10;
(or)
p[0][0] = 10;
Assigns the value 10 to the dereference pointer *p[0] (or **p or p[0][0]) updating the value at that memory address to 10.
printf("**p = %d", **p);
Prints the value stored in the block of memory pointed to by p[0] (the value accessed by dereferencing the pointer as *p[0] or **p)
The way to keep this straight in your head, is p is a single pointer of type pointer-to-pointer-to short. There are 2-level of indirection (e.g. pointer-to-pointer). To remove one level of indirection, you use the unary * operator, e.g.
*p /* has type pointer-to short */
or the [..] also acts as a dereference such that:
p[0] /* also has type pointer-to short */
You still have a pointer-to so you must remove one more level of indirection to refernce the value stored at the memory location pointed to by the pointer. (e.g. the pointer holds the address where the short is stored as its value). So you need:
**p /* has type short */
and
*p[0] /* also has type short */
as would
p[0][0] /* also has type short */
The other piece to keep straight is the type controls pointer-arithmetic. So p++ adds 8-bytes to the pointer-to-ponter address so it now points to the next pointer. If you do short *q = (*p)++; (or short *q = p[0]++, adds 2-bytes to the address for the pointer-to-short, soqnow points to the nextshortin the block of memory beginning at*p(orp[0]`). (there is no 2nd short because you only allocated 1 -- but you get the point)
Let me know if you have further questions.
Let me put it in different way,
consider an example,
int x;
int *y = &x;
int **z = &y;
x = 10;
Which simplifies to this,
Note: Only for illustration purpose I have chosen address of x,y,z as 0x1000,0x2000,0x3000 respectively.
What does *p mean in my case?
In short the snippetshort **p = (short **)malloc(sizeof(short *)); is dynamically allocating a pointer to a pointer of type short i.e same asy in my example.

What is wrong with the pointer usage in this simple program?

I'm using VS 2010 Express, and I'm on Win Vista.
Here is the code:
#include <stdio.h>
int somefunc(char *p);
int main()
{
char *p = 0;
int x;
x = somefunc (p);
printf("%c", *p);
getch();
return 0;
}
int somefunc(char *p)
{
char y = '4';
p = &y;
return 2;
}
After I return to main(), I see the following in the autos window for p:
p 0x00000000 <Bad Ptr>
Anyone know why? It's as if the pointer is being treated as an automatic variable.
Btw, the x was just to create a similar condition to the same problem I was having in a larger program, but I don't think people want to sift through all of that code just to get to the meat of the problem, which is displayed here.
p in main() is a null pointer. It is passed by value to somefunc(), but that means that the value in the variable p in the function is a copy of the value in p in the main program, not a pointer to p itself. You change what the copy of p in the function points at; fortunately, it doesn't change what's in the main program.
Then you try to print what's at the position pointed to by the null pointer; this is undefined behaviour and programs typically crash.
If you had managed to change p in the main program, it would be pointing to an automatic local variable in somefunc() that would be out of scope — which is more undefined behaviour.
This would work:
#include <stdio.h>
int somefunc(char **p);
int main(void)
{
char *p = 0;
int x = somefunc(&p);
printf("%c\n", *p);
return 0;
}
int somefunc(char **p)
{
static char y = '4';
*p = &y;
return 2;
}
There are many other, possibly better, ways to make this work too.
I'm still confused on what *p = &y; means. If p in somefunc is a pointer to the pointer p, let's say p2 is a pointer to p1, then *p2 = p1, so *p2 is p1, which stores &y? Is that the correct way of thinking about this?
Basically, yes. First, let's rewrite the code to disambiguate the use of p:
int main(void)
{
char *p1 = 0;
int x = somefunc(&p1);
printf("%c\n", *p1);
return 0;
}
int somefunc(char **ppc)
{
static char y = '4';
*ppc = &y;
return 2;
}
The variable ppc is a pointer to pointer to char (hence the name ppc — not a name I'd normally use except for pedagogical purposes). I'll also rename p in main() to pq1, and introduce char *p2; in somefunc() which is a pointer to char.
Revising your comment in terms of these variables:
I'm still confused on what *ppc = &y; means. If ppc in somefunc() is a pointer to the pointer p1 in main(), then let's say ppc is a pointer to p1, then *ppc = p1, so *ppc is p1, which stores &y? Is that the correct way of thinking about this?
And that strongly shows that you're thinking is correct. One of the design guidelines for the C type nomemclature was that if you write:
SomeType *stp;
then *stp represents a value of type SomeType — declaration mimics use.
Now, with ppc, the declaration is char **ppc; and the declaration mimics use rule means that **ppc is a value of type char. Consequently, it means that *ppc is a value of type char *. It means that when you write to *ppc, you are modifying the space that ppc points at, and it points at the address of char *p1; in main() in the sample code.
You are modifying p in somefunc but this won't modify p in main. You probably need to pass a pointer to p if you want to modify its value.
Complementing Jonathan's answer, for your question
What is the difference between char **p and char p for the function parameter? Why can I pass and modify an array without having to return it, but I have to with a pointer? They are both addresses.
In C, there's no pass by reference, there's only pass by value i.e. any argument passed to a function is copied to its parameters, but can't be made to refer to the original. This is the reason functions like swap is implemented using pointers. Example
void swap(int *x, int *y)
{
int t = *x;
*x = *y;
*y = t;
}
int a = 0, b = 1;
swap(&a, &b);
Here &a is a pointer whose value is copied onto x, thus it is pass by value (sometimes, incorrectly, called pass by reference). So I should be able to do the same when modifying pointers too, right?
Nope. Since a pointer is already pointing to something, making it point another thing needs another level of indirection. An analogy would be: you know somewhere a direction sign is pointing towards your home, by just knowing where it's pointing to (home), would you be able to change the direction it's pointing? No, you'd have to know where the sign is to go there and make it point in another direction.
Likewise, say if a variable lives at level 0 then to edit it, we go to a level further i.e. level 1 to modify it (from outside). This concept can be applied recursively; so to edit a variable at level 1, we've to go to level 2 to modify them from outside and so on. Pictorially
type: int* int int*
variable name: ptr a pptr
-------- ------- --------
value: | 1000 | --> | 1 | <-- | 1000 |
-------- ------- --------
address: 2000 1000 2400
Notice that pptr can't change where ptr is pointing to since pptr too is pointing at what ptr is pointing at a. However
int** int* int
pptr ptr a
-------- -------- -------
| 2000 | --> | 1000 | --> | 1 |
-------- -------- -------
2400 2000 1000
now pptr (int**) is in a position to modify where ptr (int*) is pointing to. If you'd to modify pptr then you to go another level higher ppptr (int***) and so on.

C, two kinds of functions

I always see two kinds of functions like the following:
void Function_1(
int** buff
)
{
int* retNb = null;
retNb = (int*) malloc(42 * sizeof(int));
*buff = retNb;
}
void Function_2(
int* retNb
)
{
retNb = (int*) malloc(42 * sizeof(int));
}
What is the difference between function_1 and function_2 ? What are their use case ?
A really big difference, they're really different - by ANY means.
Let's keep it simple:
void Function_1(int** buff)
Parameter in function 1 is a pointer to a pointer to an int named buff and what this function does is the following:
int* retNb = null;
Declaring an int pointer called retNb, the assignment to NULL here is really not necessary, though, because next line is the following:
retNb = (int*) malloc(42 * sizeof(int));
retNb is called to get the value returned from malloc. malloc allocated 42*sizeof(int) spot in memory and returned it to retNb and now it can be treated as a simple array with 42 integers and can be accessed with square brackets [] as retNb[i].
*buff = retNb;
in pointers * is the way to get to the content of the address in the variable (variable == pointer in this case) so when using *buff when buff is **buff (a pointer to a pointer) you're actually asking for the pointer buff points to. Let's say we have the code:
int** myPointerToPointer = NULL;
int* myPointer = malloc(sizeof(int));
*myPointer = 4; //or myPointer[0] = 4;
printf("%d\n", *myPointer);
myPointerToPointer = &myPointer;
printf("%d\n", *(*myPointerToPointer));
printf("%d\n", &myPointer);
printf("%d\n", *myPointerToPointer);
then the output would be:
4
4
SOME_ADDRESS
SAME_ADDRESS
because the first printing is the value of myPointer (4) and the second is the value of the value of myPointerToPointer which value is myPointer which value is 4 :P
Third and fourth outputs are the same two because the address of myPointer is actually where myPointerToPointer is pointing to.
About the second function:
void Function_2(int* retNb)
It gets an int pointer - not a pointer to a pointer - just a pointer - means it contains an address of an integer variable that can be accessed with the opeartor *.
retNb = (int*) malloc(42 * sizeof(int));
this line is assigning dynamic memory (again 42 times sizeof(int)) and now can be treated as a regular int array with 42 spots - BUT that's the only thing it does, it won't have anything point to it, just assign memory and that's it.
Hope you understand :P
In function two u are have a pointer to an array of 42 ints.
int function 1 you set buff to point to this array.

Array Pointers vs Regular Pointers in C

I am a total beginner to C so please, work with my ignorance. Why does a normal pointer
int* ptr = &a; has two spaces in memory (one for the pointer variable and one for the value it points to) and an array pointer int a[] = {5}; only has one memory space (if I print out
printf("\n%p\n", a) I get the same address as if I printed out: printf("\n%p\n", &a).
The question is, shouldn't there be a memory space for the pointer variable a and one for its value which points to the first array element? It does it with the regular pointer int* ptr = &a;
It's a little unclear from your question (and assuming no compiler optimization), but if you first declare a variable and then a pointer to that variable,
int a = 4;
int *p = &a;
then you have two different variables, it makes sense that there are two memory slots. You might change p to point to something else, and still want to refer to a later
int a = 4;
int b = 5;
int *p = &a; // p points to a
// ...
p = &b; // now p points to b
a = 6; // but you can still use a
The array declaration just allocates memory on the stack. If you wanted to do the same with a pointer, on the heap, you would use something like malloc or calloc (or new in c++)
int *p = (int*)malloc(1 * sizeof(int));
*p = 4;
but of course remember to free it later (delete in c++)
free(p);
p = 0;
The main misunderstanding here is that &a return not pointer to pointer as it expected that's because in C language there some difference between [] and * (Explanation here: Difference between [] and *)
If you try to &a if a was an pointer (e.g. int *a) then you obtain a new memory place but when your use a static array (i.e. int a[]) then it return address of the first array element. I'll also try to clarify this by mean of the next code block.
#include <stdio.h>
int main(int argc, char *argv[])
{
// for cycles
int k;
printf("That is a pointer case:\n");
// Allocate memory for 4 bytes (one int is four bytes on x86 platform,
// can be differ for microcontroller e.g.)
int c = 0xDEADBEEF;
unsigned char *b = (unsigned char*) &c;
printf("Value c: %p\n", c);
printf("Pointer to c: %p\n", &c);
printf("Pointer b (eq. to c): %p\n", b);
// Reverse order (little-endian in case of x86)
for (k = 0; k < 4; k++)
printf("b[%d] = 0x%02X\n", k, b[k]);
// MAIN DIFFERENCE HERE: (see below)
unsigned char **p_b = &b;
// And now if we use & one more we obtain pointer to the pointer
// 0xDEADBEEF <-- b <-- &p_b
// This pointer different then b itself
printf("Pointer to the pointer b: %p\n", p_b);
printf("\nOther case, now we use array that defined by []:\n");
int a[] = {5,1};
int *ptr = &a;
// 'a' is array but physically it also pointer to location
// logically it's treat differ other then real pointer
printf("'a' is array: %x\n", a);
// MAIN DIFFERENCE HERE: we obtain not a pointer to pointer
printf("Pointer to 'a' result also 'a'%x\n", &a);
printf("Same as 'a': %x\n", ptr);
printf("Access to memory that 'a' pointes to: \n%x\n", *a);
return 0;
}
This is very simple. In first case,
int* ptr = &a;
you have one variable a already declared and hence present in memory. Now you declare another variable ptr (to hold the address, in C variables which hold address of another variable are called pointers), which again requires memory in the same way as a required.
In second case,
int a[] = {5};
You just declare one variable (which will hold a collection of ints), hence memory is allocated accordingly for a[].
In this expression, int* p = &a; p has only one memory location, of the WORD size of your CPU, most probably, and it is to store the address (memory location) of another variable.
When you do *p you are dereferencing p, which means you are getting the value of what p points to. In this particular case that would be the value of a. a has its own location in memory, and p only points to it, but does not itself store as content.
When you have an array, like int a[] = {5};, you have a series (or one) of memory locations, and they are filled with values. These are actual locations.
Arrays in C can decay to a pointer, so when you printf like you did with your array, you get the same address, whether you do a or &a. This is because of array to pointer decay.
a is still the same location, and is only that location. &a actually returns a pointer to a, but that pointer sits else where in memory. If you did int* b = &a; then b here would not have the same location as a, however, it would point to a.
ptr is a variable containing a memory address. You can assign various memory addresses to ptr. a is a constant representing a fixed memory address of the first element of the array. As such you can do:
ptr = a;
but not
a = ptr;
Pointers point to an area in memory. Pointers to int point to an area large enough to hold a value of int type.
If you have an array of int and make a pointer point to the array first element
int array[42];
int *p = array;
the pointer still points to a space wide enough for an int.
On the other hand, if you make a different pointer point to the whole array, this new pointer points to a larger area that starts at the same address
int (*q)[42]; // q is a pointer to an array of 42 ints
q = &array;
the address of both p and q is the same, but they point to differently sized areas.

Not able to access array elements?

i have this array where i am trying to access its elements by incrementing ptr, as suggested here Trying to find different methods of accessing array elements?...i must be doing something stupid...please help me!
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i;
char *p1 = "Cnversions";
char *p2 = "Divided";
char *p3 = "Plain";
char *p4 = "Solid";
char *arr[3];
arr[0] = p1;
arr[1] = p2;
arr[2] = p3;
arr[3] = p4;
for(i=0;i<=3;i++)
{
printf("string at arr[%d] is: %s\n",i,*arr);
arr++;
}
return 0;
}
An array like arr is located at a specific spot in memory, so it makes no sense to increment arr (what does it mean to increment an array?)
Instead, you will need to create a pointer to the start of the array and increment the pointer:
char **ptr = arr;
for(i=0; i<4; i++) {
printf("arr[%d] = %s\n", i, *ptr);
ptr++;
}
(Note also that you need to make arr four elements big, i.e. char *arr[4], to accommodate the four string pointers you put in it.)
Remember that although we tend to think of double pointers as arrays, all the compiler sees them as are pointers. When you increment a pointer, it adds a value to the address of the pointer equal to the size of the data type it's pointing at. For example:
int *p;
p = (int *) malloc(sizeof(int));
p is pointing to an int, so the size of p's pointed data is (typically) 4 bytes. This means when you increment p, it will be pointing at a location 4 bytes greater than where it was before.
The type of arr is a char**, meaning that it's a pointer to a pointer to a char. Pointers on most machines these days are 8 bytes. So when you incrementing arr, you are effectively telling the computer to set arr to point to an address 8 bytes higher than what it was at before. In the case of arr, this is an illegal address, so you'll get some kind of crash.

Resources