C need help understanding pointer iteration - c

So I'm trying to learn some C with pointers but I'm having trouble understanding the following code snippet. first and last are the first and last item. So you have something like first, middle, last. but what is last - 1? Is it just the second last element? so if we have some thing first, last with no middle then this would be true?
item *first, item *last
if (first == last -1)
return 0

To expound on #John Bode's answer, a pointer is just a number. It's an address in memory. Arrays are laid out contiguously in memory. The first element has the lowest address, and the last element the highest address.
So, if we have the address for the first element in the array, and we add 1, we get the memory address of the next element in the array. Your compiler should know how many bytes each element in the array takes up unless you're doing weird casting on the pointers. Knowing this, the program adds that many bytes to the address.
So, to get to the next address, we simply add 1. To get to the previous address, we can subtract 1.

Imagine you have an array of item:
item arr[10];
and then you set first and last to point to the first and last items of the array, respectively:
item *first = &arr[0];
item *last = &arr[9];
which gives us something like
item item *
+---+
arr: | | arr[0] <---- first
+---+
| | arr[1]
+---+
| | arr[2]
+---+
...
+---+
| | arr[8] <---- last - 1
+---+
| | arr[9] <---- last
+---+
The expression last - 1 gives you a pointer to the object immediately before the object pointed to by last, assuming both objects are members of the same array, or that last points to an object immediately following the end of the array.
C doesn't guarantee that individual variables are laid out in any specific order, so adding or subtracting an offset to a pointer only works (that is, gives you a useful result) if you're pointing to an element of an array. IOW, if you had something like
item a;
item b;
item *first = &a;
item *last = &b;
then the expression last - 1 isn't guaranteed to point to a (nor is first + 1 guaranteed to point to b).

Yet another pointer math illustration
Not knowing the type of item in your example code, I will choose to make it a struct:
typedef struct {
int a;
int b;
float c;
} item_s;//new type
Using the new type item_s, create the following array and a set of pointers to illustrate pointer arithmetic
item_s item[5] = {{1,2,3.0},{10,20,30.0},{15,25,35.0},{16,26,36.0},{17,27,37.0}};
item_s *first, *last, *index;
//set the `first` and `last` pointers to the first and last element of the array
first = &item[0];
last = &item[4];
//now illustrate type of pointer manipulation and its results
index = first + 1 ;// index now points to the area of memory occupied by item[1]
// first + 1*sizeof(item_s)
printf("a: %d\nb: %d\nc:%f\n", index->a, index->b, index->c);
index = last - 1;//index points to the area of memory occupied by item[3]
// last - 1*sizeof(item_s)
printf("a: %d\nb: %d\nc:%f\n", index->a, index->b, index->c);
index = last + 1;//index points to an un-owned area of memory and possibly a seg-fault.
//printf("a: %d\nb: %d\nc:%f\n", index->a, index->b, index->c);//UB
So when you increment a pointer by 1, the new memory location pointed to is exactly the
old memory location + 1 * sizeof(pointer type)
If you increment it by 3, then it is
old memory location + 3 * sizeof(pointer type)

Related

Order of operations for accessing the memory address of a list item?

Suppose I had an extremely basic C code that simply printed the memory address of an element inside the list such as
#include <stdio.h>
int main()
{
int data[5] = {1,2,3,4,5};
printf("%x", &data[2]);
return 0;
}
What is the order of operations for the &data[2] call?
I am finding it hard to visually see because data[2] returns a number, and getting the memory address of a number "3" doesn't really make sense.
When you create an array, the compiler will reserve memory for it, and you can store values in that memory.
What is returned by e.g. &data[2] is not a pointer to the integer 3 but a pointer to the array element where you have opted to store the integer value 3.
An array like yours look like this in memory
+---------+---------+---------+---------+---------+
| data[0] | data[1] | data[2] | data[3] | data[4] |
+---------+---------+---------+---------+---------+
The exact values stored in each element is kind of irrelevant if all you want is a pointer to an element.
In C the syntax array[index] is just syntactic sugar for *(array + index) and the address-of operator &array[index] can be rewritten as just (array + index), which is what you're taking the address of with the statement &data[2]. You aren't getting the address of the value at data[2] (i.e. 3); you're getting the address of (data + 2).
Try this:
int data[5] = {1,2,3,4,5};
printf("%p\n", (void *)&data[2]);
printf("%p\n", (void *)(data + 2));
You will see the same address on both lines.

A kind of Linked List but Don't understand exactly

I asked this before, but no one answered so revise my questions. I have tried to analyze this codes but it doesn't make sense for me. This time hopefully someone give me an idea or correct my misunderstanding.
char * p pointing to command array is type-casted to CMD_BLOCK * after getting thru a couple of functions.
extern CHGR_CMD command[96]
+---+---+---+---+
(CMD_BLOCK *(char *p)) -> | CHGR_CMD | command[0]
+---+---+---+---+
| CHGR_CMD | command[1]
+---+---+---+---+ ....
| .... | command[95]
+---+---+---+---+
Here is a struct of CMD_BLOCK and union CHGR_CMD
typedef struct cmd_block {
struct cmd_block *next;
short type;
short unused;
CHGR_CMD c; //Union
} CMD_BLOCK;
typedef union chgr_cmd {
NET_HDR n; //struct
CHGR_SC_SETUP su;//struct
CHGR_SC_START st;//struct
CHGR_SC_STOP sp;//struct
....
} CHGR_CMD;
the below variables are used in cmd_init()
#define CMD_OFFSET (sizeof(struct cmd_block *) + 2*sizeof(short))
block_size = sizeOf(CHGR_CMD)
size = 96*sizeOf(CHGR_CMD)
Especially, I don't get the for loop below:
int cmd_init(register char* p, register long size, int block_size)
{
int i;
if((size <= 0) || (block_size <= 0) || (block_size > size))
return(-1);
cmd_out_head = NULL;//extern var
cmd_out_tail = NULL;//extern var
cmd_free_space = NULL;//extern var
block_size += CMD_OFFSET;// turn to be size of CMD_BLOCK
cmd_blocks_free = 0;
cmd_blocks_used = 0;
for(i=0; size >= block_size; size-=block_size, i++, p+=block_size) {
((CMD_BLOCK *)(p))->next = cmd_free_space;
cmd_free_space = (CMD_BLOCK *)(p);
cmd_blocks_free++;
}
cmd_b = NULL;
status_seq_clear();
return(i);
}
for loop iterates until 96 which is size of command array.
p+=block_size keeps adding size of CMD_BLOCK ---> I don't get how this works?. Initially type of array was CHGR_CMD and type-casting to char * then another casting to CMD_BLOCK * then increasing the size of CMD_BLOCKin for-loop??
I am not sure but assumed that type of command array is now turning to be CMD_BLOCK after a couple of type-casting.
Another thing I don't get is this codes:
((CMD_BLOCK *)(p))->next = cmd_free_space;
cmd_free_space = (CMD_BLOCK *)(p);
It doesn't seem like linking together. cmd_free_space seems to point the last element of the array while * p gets increased by the size of CMD_BLOCK.
Regarding the cast from char* to CMD_BLOCK*, It is hard to tell without looking at more code, but most probably the original programmer wanted to give some opacity to the p parameter, that is, maybe he/she didn't want to expose the fact that the function is receiving an array of CMD_BLOCK structs.
This opacity is sometimes exercised on certain APIs to try to minimize the chance that a data structure is directly manipulated by the programmer, bypassing the tested API.
See here for more details on opaque pointers.
In order to remove the opacity, a programmer needs to explicitly cast the opaque pointer to the concrete type that is actually being passed. This is what seems that is being done with the line ((CMD_BLOCK *)(p))->next = cmd_free_space;
As to what the for block is doing, it is actually building a reversed linked list from an array of contiguous CMD_BLOCK structures. The first node's next pointer is initialized to NULL, becoming the tail of the linked list, the second node's next pointer is pointed to the first node and so forth, until the last block becomes the head of the list and seems to be accessible through the cmd_free_space variable as you point out.
** EDIT **
To better illustrate how the list is built, I'll try to step through the first two iterations.
iteration 1
State at the beginning of the iteration:
cmd_free_space is NULL;
p is pointing to the first element of the array.
Execution:
p->next = cmd_free_space; p->next becomes NULL;
cmd_free_space = p; cmd_free_space is pointing to the first element of the array
p += block_size; p is now pointing to the second element of the array
iteration 2
State at the beginning of the iteration:
cmd_free_space is pointing to the first element of the array
p is pointing to the second element of the array.
Execution:
p->next = cmd_free_space; p->next = first element of the array (link is done)
cmd_free_space = p; cmd_free_space is now pointing to the second element of the array
p += block_size; p is now pointing to the third element of the array
and so on...
** END OF EDIT **
I would remove from the for block the i variable, as it is useless (it is neither controlling the number of iterations nor indexing anything).
** EDIT: **
I hadn't noticed that the ´i´ variable is returned from the function, so it most probably has a purpose, outside of the function. The function is actually returning the number of elements that were actually processed in the for loop.
** END OF EDIT **
The fact that blocksize is a variable parameter and not simply sizeof(CMD_BLOCK) may also indicate that the function can initialize a linked list with an array of structs that contain as first member a CMD_BLOCK struct, but that also carry additional data. By adding blocksize to the pointer that is walking the array, the for loop would effectively skip over the extra data.
This initialization of an array into a linked list may seem a strange thing to do, but I would guess that the programmer needed the flexibility of inserting commands in the middle of the list without having to copy/move elements in the original array to make space.

Confused About Pointers in C and changing data at memory addresses

I think I will understand this concept better if someone can assist me in a current project that I'm working on. I want to use C to edit data at specific memory addresses, using pointers. Specifically, I have two character arrays (strings) which I need to both read data from at specific locations, and also write to at specific locations.
I'm mostly confused about syntax of pointers, such as * and -> and &.
From my understanding, the * refers to the data kept at the current memory address of the pointer. So, for example, if I wanted to edit the data at the beginning memory address of a char *p, I would do something like: (*p) = 'c';
Now, what if I wanted do to alter a character at the 2nd memory address from the beginning of p?
Also, I understand that & refers to the location of the pointer. But I don't know how to use this syntax.
Here is my example:
int orig_length = strlen(original_string); //-1 for \0?
char *poriginal, *pnew_string;
poriginal = &original_string;
while(orig_length>0) {
k = 0;
j = 0;
while(isalpha(*(poriginal+j))) {
j++;
k++;
}
while(k > 0) {
*(pnew_string+(j-k)) = toupper(*(poriginal+k-1)); //toupper
k--;
}
if(*(poriginal+(j)) == '_') {
*(pnew_string+(j)) = ' ';
}
else {
*(pnew_string+(j)) = *(poriginal+(j));
}
orig_length = orig_length - j;
}
*(pnew_string+strlen(pnew_string)) = '\0'; //Syn? Is this actually necessary?
... //program continues...
By the way, this program is meant to take one string "now_i_understand!" and reverse each word, capitalize each word, switch _ to ' ', and leave other punctuation alone: "WON I DNATSREDNU!"
If what you are dealing with is an array of characters (and it is), use array syntax:
pnew_string[j+1] = poriginal[j+1];
Note that this syntax is equivalent to:
*(pnew_string + j + 1) = *(poriginal + j + 1);
but is more readable.
Dealing with most of the other cases you've got should be obvious given this example.
The * and & operators are inverses of each other. A pointer object hold the address of some other object in memory (or it old a null pointer, which doesn't point to any object).
The unary * operator takes a pointer operand, and gives you the object that it points to; this is called dereferencing.
The unary & operator takes an operand that refers to an object of any type, and gives you a pointer to that object. & is the address-of operator.
For example:
int obj = 42; /* obj is an object of type int; it currently holds the value 42 */
int *ptr; /* ptr is a pointer to an int */
ptr = &obj; /* ptr now holds the address of obj */
printf("obj = %d\n", obj); /* prints 42 */
printf("*ptr = %d\n", *ptr); /* also prints 42; *ptr is another name for obj */
The -> operator is shorthand for dereferencing a pointer and accessing a member of what it points to. The prefix must be a pointer to a struct or union. foo->bar means the same thing as (*foo).bar, where foo is a pointer and bar is the name of a member of what foo points to.
You can also perform arithmetic on pointers. If ptr is a pointer pointing to an element of an array, then ptr + 1 points to the next element of the array, ptr + 2 points to the element after that, and so forth.
The [] array indexing operator is actually defined in terms of pointer arithmetic. ptr[2] means exactly the same thing as *(ptr+2). Combine that with the fact that an array name, in most contexts, decays to a pointer to the array's first element, and with a little thought you'll see how arr[2] refers to the third element of the array arr (third because indexing starts at 0).
I strongly recommend sections 4 (Pointers) and 6 (Arrays and Pointers) of the comp.lang.c FAQ; it will likely explain this stuff better than I have.

2D array and pointer in C - how to access elements?

I have an example involving a pointer to a 2D array. Can someone help me understand what is going on in this example?
int main()
{
int i = 0, j=0, sum0=0, sum1=0;
int data[4][3] = { {23,55,50},{45,38,55},{70,43,45},{34,46,60}};
int *Ptr;
Ptr = *data; //Why is the indirection operator used here?
// Does Ptr = 23 by this assignment?
for (i=0; i<4; i++) {
sum1 = 0;
for (j = 0; j < 3; j++) {
sum1 += data[i][j];
}
if (sum1 > sum0) {
sum0 = sum1;
Ptr = *(data + i); // Seems like this statement makes Ptr
} // point one row below ... what syntax
} // can you use to access columns then?
// Is it possible to use pointer arithmetic
for (i=0; i<3; i++) // to access elements of data[i][j] that
printf("%d\n", Ptr[i]); // are not at j = 0?
return 0;
}
data is a 2 dimentional array, which has 4 rows and each row has 3 elements (ie 4 X 3).
Now, Ptr = *data; means you are storing the starting address of 1st row to the pointer variable Ptr. This statement is equivalent to Ptr = *(data + 0). Ptr = *(data + 1) - this means we are assigning 2nd row's starting address.
Then *Ptr or *(Ptr + 0) will give you the value of the first element of the row to which is pointing. Similarly, *(Ptr + 1) will give you the value of the second element of the row.
The for loop in your program is used to identify which row has the maximum value of the sum of its elements (3 elements). Once the control comes out of that for loop, Ptr will be pointing to the row which has the maximum sum of its elements and sum0 will have the value of the sum.
Consider an array int a[5];, I hope you know that a[0] and 0[a] is the same. This is because a[0] means *(a+0) and 0[a] means *(0 + a). This same logic can be used in 2 dimensional array.
data[i][j] is similar to *(*(data + i) + j). We can write it as i[data][j] also.
For more details please refer to the book "Understanding Pointers in C" by Yashavant Kanetkar.
Ptr = *data; is short for *(data+0)+0 which is a pointer for first column element of the first row. the first 0 added with data is the row no., which is indirected and takes us to the first row. * (data+0) is still a address and not a value it points to (for 2D array). So, Ptr now points to the address of first column in first row. The second zero is the column no.. So, first row and first column's memory address is chosen. Using indirection (*) again would only now give value that the address holds. like * (*(data+0)+0) or **data.
Generally, if p is pointer name,i row number and j column number,
(*(p+i)+j) would give a memory address of a element in 2D array. i is row no. and j is col no.,
*(*(p+i)+j) would give the value of that element.
*(p+i) would access the ith row
to access columns, add column number to *(p+i). You may have to declare the pointer as (*p)[columns] instead of just *p. Doing so, you are declaring pointer to an 2D array.
Using pointer arithmetic is treating 2d array like 1D array. Initialize pointer *Ptr to first element (int *Ptr = *data) and then add an no. (Ptr + n) to access the columns. Adding a number higher than column number would simply continue counting the elements from first column of next row, if that exists.
data is an array of 3-element arrays of integers. In contexts that expect a "pointer to foo", you can use an "array of foo" and it will behave like a pointer to its first element, so *data is a pointer to the first element of data, namely (so to speak) {23,55,50}.
So, the answer to the first question in the comments: No, it isn't true that Ptr = 23. (It couldn't be; Ptr is an int * and 23 is an int.)
You are correct that Ptr = *(data+i) makes Ptr point to the ith row of data. More precisely, data is an array of 3-element arrays of int, which behaves like a pointer to 3-element arrays of int; adding i to it moves past i such arrays.
The usual way to access other columns of the array is ordinary array indexing. If you refer to data[i][j], you're getting column j of row i. If you want to do it with explicit pointer arithmetic, then note that (e.g.) Ptr in the example code is of type "pointer to integer", so Ptr+1 (for instance) is element 1 of whatever row Ptr is pointing to. (But, as a matter of style, you should generally not do explicit pointer arithmetic when you don't actually need to.)
In your example the loop goes through all matrix rows to find the one whose sum of all elements holds the maximum value.
At the beginning a pointer to the first row is assigned:
Ptr = *data;
Which means that the following is true:
(Ptr[0] == 23 && Ptr[1] == 55 && Ptr[2] == 50)
Notice that Ptr is a pointer so it holds a memory address, hence Ptr is different than 23 (unless the memory address happens to be 23, which is unlikely to happen).
C allows multidimensional arrays, lays them out in memory as contiguous locations, and does more behind the scenes address arithmetic.
Consider a 2-dimensional array.
int arr[ 3 ][ 3 ] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
The compiler treats a 2 dimensional array as an array of arrays.
where an array name is a pointer to the first element within the array.
So, arr points to the first 3-element array, which is actually the first row (i.e., row 0) of the two-dimensional array.
Similarly, (arr + 1) points to the second 3-element array (i.e., row 1) and so on.
The value of this pointer, (arr + 1), refers to the entire row.
Since row 1 is a one-dimensional array, (arr + 1) is actually a pointer to the first element in row 1.
Now add 2 to this pointer. Hence, ((arr + 1) + 2) is a pointer to element 2 (i.e., the third element) in row 1. The value of this pointer, ((arr + 1) + 2), refers to the element in column 2 of row 1.

How do pointer-to-pointers work in C? (and when might you use them?)

How do pointers-to-pointers work in C?
When might you use them?
Let's assume an 8 bit computer with 8 bit addresses (and thus only 256 bytes of memory). This is part of that memory (the numbers at the top are the addresses):
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
| | 58 | | | 63 | | 55 | | | h | e | l | l | o | \0 | |
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
What you can see here, is that at address 63 the string "hello" starts. So in this case, if this is the only occurrence of "hello" in memory then,
const char *c = "hello";
... defines c to be a pointer to the (read-only) string "hello", and thus contains the value 63. c must itself be stored somewhere: in the example above at location 58. Of course we can not only point to characters, but also to other pointers. E.g.:
const char **cp = &c;
Now cp points to c, that is, it contains the address of c (which is 58). We can go even further. Consider:
const char ***cpp = &cp;
Now cpp stores the address of cp. So it has value 55 (based on the example above), and you guessed it: it is itself stored at address 60.
As to why one uses pointers to pointers:
The name of an array usually yields the address of its first element. So if the array contains elements of type t, a reference to the array has type t *. Now consider an array of arrays of type t: naturally a reference to this 2D array will have type (t *)* = t **, and is hence a pointer to a pointer.
Even though an array of strings sounds one-dimensional, it is in fact two-dimensional, since strings are character arrays. Hence: char **.
A function f will need to accept an argument of type t ** if it is to alter a variable of type t *.
Many other reasons that are too numerous to list here.
How do pointers to pointers work in C?
First a pointer is a variable, like any other variable, but that holds the address of a variable.
A pointer to a pointer is a variable, like any other variable, but that holds the address of a variable. That variable just happens to be a pointer.
When would you use them?
You can use them when you need to return a pointer to some memory on the heap, but not using the return value.
Example:
int getValueOf5(int *p)
{
*p = 5;
return 1;//success
}
int get1024HeapMemory(int **p)
{
*p = malloc(1024);
if(*p == 0)
return -1;//error
else
return 0;//success
}
And you call it like this:
int x;
getValueOf5(&x);//I want to fill the int varaible, so I pass it's address in
//At this point x holds 5
int *p;
get1024HeapMemory(&p);//I want to fill the int* variable, so I pass it's address in
//At this point p holds a memory address where 1024 bytes of memory is allocated on the heap
There are other uses too, like the main() argument of every C program has a pointer to a pointer for argv, where each element holds an array of chars that are the command line options. You must be careful though when you use pointers of pointers to point to 2 dimensional arrays, it's better to use a pointer to a 2 dimensional array instead.
Why it's dangerous?
void test()
{
double **a;
int i1 = sizeof(a[0]);//i1 == 4 == sizeof(double*)
double matrix[ROWS][COLUMNS];
int i2 = sizeof(matrix[0]);//i2 == 240 == COLUMNS * sizeof(double)
}
Here is an example of a pointer to a 2 dimensional array done properly:
int (*myPointerTo2DimArray)[ROWS][COLUMNS]
You can't use a pointer to a 2 dimensional array though if you want to support a variable number of elements for the ROWS and COLUMNS. But when you know before hand you would use a 2 dimensional array.
I like this "real world" code example of pointer to pointer usage, in Git 2.0, commit 7b1004b:
Linus once said:
I actually wish more people understood the really core low-level kind of coding. Not big, complex stuff like the lockless name lookup, but simply good use of pointers-to-pointers etc.
For example, I've seen too many people who delete a singly-linked list entry by keeping track of the "prev" entry, and then to delete the entry, doing something like:
if (prev)
prev->next = entry->next;
else
list_head = entry->next;
and whenever I see code like that, I just go "This person doesn't understand pointers". And it's sadly quite common.
People who understand pointers just use a "pointer to the entry pointer", and initialize that with the address of the list_head. And then as they traverse the list, they can remove the entry without using any conditionals, by just doing a
*pp = entry->next
Applying that simplification lets us lose 7 lines from this function even while adding 2 lines of comment.
- struct combine_diff_path *p, *pprev, *ptmp;
+ struct combine_diff_path *p, **tail = &curr;
Chris points out in the comments to the 2016 video "Linus Torvalds's Double Pointer Problem".
kumar points out in the comments the blog post "Linus on Understanding Pointers", where Grisha Trubetskoy explains:
Imagine you have a linked list defined as:
typedef struct list_entry {
int val;
struct list_entry *next;
} list_entry;
You need to iterate over it from the beginning to end and remove a specific element whose value equals the value of to_remove.
The more obvious way to do this would be:
list_entry *entry = head; /* assuming head exists and is the first entry of the list */
list_entry *prev = NULL;
while (entry) { /* line 4 */
if (entry->val == to_remove) /* this is the one to remove ; line 5 */
if (prev)
prev->next = entry->next; /* remove the entry ; line 7 */
else
head = entry->next; /* special case - first entry ; line 9 */
/* move on to the next entry */
prev = entry;
entry = entry->next;
}
What we are doing above is:
iterating over the list until entry is NULL, which means we’ve reached the end of the list (line 4).
When we come across an entry we want removed (line 5),
we assign the value of current next pointer to the previous one,
thus eliminating the current element (line 7).
There is a special case above - at the beginning of the iteration there is no previous entry (prev is NULL), and so to remove the first entry in the list you have to modify head itself (line 9).
What Linus was saying is that the above code could be simplified by making the previous element a pointer to a pointer rather than just a pointer.
The code then looks like this:
list_entry **pp = &head; /* pointer to a pointer */
list_entry *entry = head;
while (entry) {
if (entry->val == to_remove)
*pp = entry->next;
else
pp = &entry->next;
entry = entry->next;
}
The above code is very similar to the previous variant, but notice how we no longer need to watch for the special case of the first element of the list, since pp is not NULL at the beginning. Simple and clever.
Also, someone in that thread commented that the reason this is better is because *pp = entry->next is atomic. It is most certainly NOT atomic.
The above expression contains two dereference operators (* and ->) and one assignment, and neither of those three things is atomic.
This is a common misconception, but alas pretty much nothing in C should ever be assumed to be atomic (including the ++ and -- operators)!
When covering pointers on a programming course at university, we were given two hints as to how to begin learning about them. The first was to view Pointer Fun With Binky. The second was to think about the Haddocks' Eyes passage from Lewis Carroll's Through the Looking-Glass
“You are sad,” the Knight said in an anxious tone: “Let me sing you a song to comfort you.”
“Is it very long?” Alice asked, for she had heard a good deal of poetry that day.
“It's long,” said the Knight, “but it's very, very beautiful. Everybody that hears me sing it - either it brings the tears to their eyes, or else -”
“Or else what?” said Alice, for the Knight had made a sudden pause.
“Or else it doesn't, you know. The name of the song is called ‘Haddocks' Eyes.’”
“Oh, that's the name of the song, is it?" Alice said, trying to feel interested.
“No, you don't understand,” the Knight said, looking a little vexed. “That's what the name is called. The name really is ‘The Aged Aged Man.’”
“Then I ought to have said ‘That's what the song is called’?” Alice corrected herself.
“No, you oughtn't: that's quite another thing! The song is called ‘Ways And Means’: but that's only what it's called, you know!”
“Well, what is the song, then?” said Alice, who was by this time completely bewildered.
“I was coming to that,” the Knight said. “The song really is ‘A-sitting On A Gate’: and the tune's my own invention.”
Pointers to Pointers
Since we can have pointers to int, and pointers to char, and pointers to any structures we've defined, and in fact pointers to any type in C, it shouldn't come as too much of a surprise that we can have pointers to other pointers.
Consider the below figure and program to understand this concept better.
As per the figure, ptr1 is a single pointer which is having address of variable num.
ptr1 = &num;
Similarly ptr2 is a pointer to pointer(double pointer) which is having the address of pointer ptr1.
ptr2 = &ptr1;
A pointer which points to another pointer is known as double pointer. In this example ptr2 is a double pointer.
Values from above diagram :
Address of variable num has : 1000
Address of Pointer ptr1 is: 2000
Address of Pointer ptr2 is: 3000
Example:
#include <stdio.h>
int main ()
{
int num = 10;
int *ptr1;
int **ptr2;
// Take the address of var
ptr1 = &num;
// Take the address of ptr1 using address of operator &
ptr2 = &ptr1;
// Print the value
printf("Value of num = %d\n", num );
printf("Value available at *ptr1 = %d\n", *ptr1 );
printf("Value available at **ptr2 = %d\n", **ptr2);
}
Output:
Value of num = 10
Value available at *ptr1 = 10
Value available at **ptr2 = 10
A pointer-to-a-pointer is used when a reference to a pointer is required. For example, when you wish to modify the value (address pointed to) of a pointer variable declared in a calling function's scope inside a called function.
If you pass a single pointer in as an argument, you will be modifying local copies of the pointer, not the original pointer in the calling scope. With a pointer to a pointer, you modify the latter.
A pointer to a pointer is also called a handle. One usage for it is often when an object can be moved in memory or removed. One is often responsible to lock and unlock the usage of the object so it will not be moved when accessing it.
It's often used in memory restricted environment, ie the Palm OS.
computer.howstuffworks.com Link>>
www.flippinbits.com Link>>
it's a pointer to the pointer's address value. (that's terrible I know)
basically, it lets you pass a pointer to the value of the address of another pointer, so you can modify where another pointer is pointing from a sub function, like:
void changeptr(int** pp)
{
*pp=&someval;
}
You have a variable that contains an address of something. That's a pointer.
Then you have another variable that contains the address of the first variable. That's a pointer to pointer.
A pointer to pointer is, well, a pointer to pointer.
A meaningfull example of someType** is a bidimensional array: you have one array, filled with pointers to other arrays, so when you write
dpointer[5][6]
you access at the array that contains pointers to other arrays in his 5th position, get the pointer (let fpointer his name) and then access the 6th element of the array referenced to that array (so, fpointer[6]).
How it works:
It is a variable that can store another pointer.
When would you use them :
Many uses one of them is if your function wants to construct an array and return it to the caller.
//returns the array of roll nos {11, 12} through paramater
// return value is total number of students
int fun( int **i )
{
int *j;
*i = (int*)malloc ( 2*sizeof(int) );
**i = 11; // e.g., newly allocated memory 0x2000 store 11
j = *i;
j++;
*j = 12; ; // e.g., newly allocated memory 0x2004 store 12
return 2;
}
int main()
{
int *i;
int n = fun( &i ); // hey I don't know how many students are in your class please send all of their roll numbers.
for ( int j=0; j<n; j++ )
printf( "roll no = %d \n", i[j] );
return 0;
}
A 5-minute video explaining how pointers work:
There so many of the useful explanations, but I didnt found just a short description, so..
Basically pointer is address of the variable.
Short summary code:
int a, *p_a;//declaration of normal variable and int pointer variable
a = 56; //simply assign value
p_a = &a; //save address of "a" to pointer variable
*p_a = 15; //override the value of the variable
//print 0xfoo and 15
//- first is address, 2nd is value stored at this address (that is called dereference)
printf("pointer p_a is having value %d and targeting at variable value %d", p_a, *p_a);
Also useful info can be found in topic What means reference and dereference
And I am not so sure, when can be pointers useful, but in common it is necessary to use them when you are doing some manual/dynamic memory allocation- malloc, calloc, etc.
So I hope it will also helps for clarify the problematic :)

Resources