Creating a singly-linked list - c

I have a function to join two structs to create a linked list.
Here, is the code:
struct point{
int x;
int y;
struct point *next;
};
void printPoints(struct point *);
void printPoint(struct point *);
struct point * append(struct point *, struct point *);
void main(){
struct point pt1={1,-1,NULL};
struct point pt2={2,-2,NULL};
struct point pt3={3,-3,NULL};
struct point *start, *end;
start=end=&pt1;
end=append(end,&pt2);
end=append(end,&pt3);
printPoints(start);
}
void printPoint(struct point *ptr){
printf("(%d, %d)\n", ptr->x, ptr->y);
}
struct point * append(struct point *end, struct point *newpt){
end->next=newpt;
return newpt;
}
void printPoints(struct point *start){
while(start!=NULL){
printPoint(start);
start=start->next;
}
}
Here, the append function's task involves changing the end pointer.
Both the arguments of append function are pointers; in 1st case, 1st argument is &pt1 and 2nd argument is &pt2.
The function makes a copy of the end pointer which has the type struct point.
Since &pt1 is passed then this duplicate end pointer has x component as 1 and y component as -1 and next component as NULL.
Now we change this copy's next component to newpt pointer and return the newpt pointer.
Back to the main function, the original end pointer now has the value of &pt2.
end->next = newpt; shouldn't produce any change in the original end pointer in main because only the local pointer was changed.
So then why do I get a linked list.
What I get:
(1, -1)
(2, -2)
(3, -3)
What I think I should get:
(1, -1)

end->next = newpt; shouldn't produce any change in the original end pointer in main. Because, only the local pointer was changed
Not quite correct. It is true that when you call append, a copy of end is made. However, the -> operator dereferences what that pointer points to. You would get the same behavior with (*end).. Since the end in main is the same as the end in append, they both point to the same thing. You could have 100 copies of a pointer, all pointing to the same thing. If you choose one, follow what it points to and change that, then you've changed the same thing that all other 99 pointers point to. Furthermore, you reassign end in main by returning newpt, so each call to append results in an updated end. The output you observe is correct. Consider the condensed stack frames:
In main, at first call to append:
____main____
|___pt1____| <----+ <-+
|x=1 y=-1 | | |
|_next=NULL| | |
|___pt2____| | |
|___pt3____| | |
|__start___|------+ |
|___end____|-----------+ // cell sizes NOT drawn to scale
// start and end both point to pt1
Now, on the first call to append, the main stack frame stays the same, and a new one is created for append, where end and the address to pt2 are passed in.
|___main____
|___pt1____| <----+ <-+
|_next=NULL| | | // x and y omitted for brevity
|___pt2____| | |
|___pt3____| | |
|___end____|------+ |
|
___append__ |
|___&pt2___| |
|___end____|-----------+ // also points to pt1 back in main
When you use the -> operator, you dereference what that pointer points to. In this case, pt1, so both end in main and end in append point to pt1. In append, you do
end->next = newpt;
which is the address of pt2. So now your stack frames look like this:
|___main____
|___pt1____| <-----------+ <-+
|_next=&pt2|------+ | | // x and y omitted for brevity
| | | | | // (made pt1 cell bigger just to make the picture clearer, no other reason)
|__________| | | |
|___pt2____| <----+ | |
|___pt3____| | |
|___end____|-------------+ |
|
___append__ |
|___&pt2___| |
|___end____|------------------+ // also points to pt1 back in main
Finally, when you return from append, you return the address of pt2 and assign it to end, so your stack in main looks like this before the 2nd call to append (again, some cells made larger for picture clarity, this does not suggest anything grew in size):
____main____
|___pt1____| <-----------+
|_next=&pt2|---+ |
| | | |
|__________| | |
|___pt2____| <-+ <-+ |
|___pt3____| | |
|___end____|-------+ |
|___start__|-------------+ // flipped start and end position to make diagram cleaner, they don't really change positions on the stack
And you do it all again with your next call to append, passing in end (now points to pt2) and the address of pt3. After all the calls to append, start points to pt1, pt1->next points to pt2, and pt2->next points to pt3, just as you see in the output.
One final note, you have an incorrect function signature for main

As in the illustration start still points to p1 and end points to pt3.
void main(){
struct point pt1={1,-1,NULL};
struct point pt2={2,-2,NULL};
struct point pt3={3,-3,NULL};
struct point *start, *end;
start=end=&pt1;
end=append(end,&pt2);
end=append(end,&pt3);
printPoints(start);
}
As in the main function, you make start and end to point at pt1.
That's why any changes made to end is also seen from start.
struct point * append(struct point *end, struct point *newpt){
end->next=newpt;
return newpt;
}
In the append function, end->next=newpt which sets the next of end to newpt. In the first case, when end points pt1, the next is set to point at pt2. This change in the list is also seen from start.
Hence, the output you are getting is correct.
Changing Pointers
When you pass a pointer to a function, the value of the pointer (that is, the address) is copied into the function not the value it is pointing at.
So, when you dereference the pointer and change it, the change is also seen from any pointer which contain the same address.
Remember that p->next is the same as (*p).next.
void change_the_pointer_reference(int* ip)
{
int i = 1;
*ip = i;
printf("%d\n", *ip); // outputs 1
}
int main()
{
int i = 0;
change_the_pointer_reference(&i);
printf("%d\n", i); // outputs 1
}
But as the value of the pointer is copied, if you assign to the pointer, this change is only seen locally.
void change_the_pointer(int* ip)
{
int i = 1;
ip = &i;
printf("%d\n", *ip); // outputs 1
}
int main()
{
int i = 0;
change_the_pointer(&i);
printf("%d\n", i); // outputs 0
}
Last final note, you have an incorrect signature of main

Related

When passing a pointer as an argument is the address & symbol not required / automatically added by compiler?

In the below code, a *Pointer is passed to a function.
The address & symbol is omitted.
The functions can still modify the value in the passed pointer.
Does the compiler auto-add the &?
char * input();
void get_command() {
char * command_pointer = input();
char * second = second_arg(command_pointer); //second needs to be before first
char * first = first_arg(command_pointer); //becuase first adds a /0
choose(first, second);
free(command_pointer);
}
char * first_arg(char * arg) {
char * j = strchr(arg, '-');
if(j==NULL) {
return arg;
}
*j = '\0';
return arg;
}
char * second_arg(char * arg) {
char * j = strchr(arg, '-');
if( j==NULL ) {
return NULL;
}
return ++j;
}
Does the compiler auto-add the &?
No. & gets the address of a variable, and the address of command_pointer isn't passed. Only its value (the address of the buffer) is passed.
The functions can still modify the value in the passed pointer.
No, they can't. They can't modify (the value of) the pointer. They can only modify that to which the pointer points.
first_arg and second_arg can't change command_pointer (the variable in get_command) because they don't know anything about it and they don't have a pointer to it.
e.g. arg = NULL; would have no effect on command_pointer.
However, they can modify the data to which command_pointer points (the chars), because they have a copy of the same pointer.
e.g. *arg = 0 (aka arg[0] = 0;) would effect *command_pointer (aka command_pointer[0]).
Let's illustrate some of the variables of get_command and first_arg.
input()'s rv Buffer allocated by input
+----------+ +---+---+---+---+---+---+---
| 0x1000 -------+--->| | | | | | | ...
+----------+ | +---+---+---+---+---+---+---
| ^
command_pointer | |
+----------+ | |
| 0x1000 -------+ |
+----------+ | |
| |
arg | j |
+----------+ | +----------+ |
| 0x1000 -------+ | 0x1004 ---------+
+----------+ +----------+
input() returns an address to a bufer it allocated (0x1000 in the diagram).
The value returned by input() is copied into command_pointer.
The value of command_pointer is copied into arg.
A value based on arg is stored in j.
get_command can modify command_pointer and the buffer.
first_arg can modify arg, j and the buffer, but not command_pointer.
The value is changed only if you use the * on the pointer. if you will not the value will not change, the address will change. Consider these functions:
char * first_arg(char * arg) {
arg = 'a';
// some other code //
}
char * second_arg(char * arg) {
*arg = 'c';
// some other code //
}
the first function will change the address that arg is pointing at. This function can be dangerous because we don't now what is stored in the address 'a'. This function may change the behavior of otter scopes in an unexpected way. but it will not change the value that arg is pointing at. (except of the scenario that you hardcode the exact address of arg)
the second function will change the value in the address arg is pointing at. This is the well defined behavior that we are looking for. This will only change the value of the memory arg is pointing at.

C need help understanding pointer iteration

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)

I have three loops over an array of (char*) elements in C. Why does the third fail?

While experimenting with methods for stepping through an array of strings in C, I developed the following small program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char* string;
int main() {
char *family1[4] = {"father", "mother", "son", NULL};
string family2[4] = {"father", "mother", "son", NULL};
/* Loop #1: Using a simple pointer to step through "family1". */
for (char **p = family1; *p != NULL; p++) {
printf("%s\n", *p);
}
putchar('\n');
/* Loop #2: Using the typedef for clarity and stepping through
* family2. */
for (string *s = family2; *s != NULL; s++) {
printf("%s\n", *s);
}
putchar('\n');
/* Loop #3: Again, we use the pointer, but with a unique increment
* step in our for loop. This fails to work. Why? */
for (string s = family2[0]; s != NULL; s = *(&s + 1)) {
printf("%s\n", s);
}
}
My specific question involves the failure of Loop #3. When run through the debugger, Loops #1 and #2 complete successfully, but the last loop fails for an unknown reason. I would not have asked this here, except for the fact that is shows me that I have some critical misunderstanding regarding the "&" operator.
My question (and current understanding) is this: family2 is an array-of-pointer-to-char. Thus, when s is set to family2[0] we have a (char*) pointing to "father". Therefore, taking &s should give us the equivalent of family2, pointing to the first element of family2 after the expected pointer decay. Why doesn't, then,
*(&s + 1) point to the next element, as expected?
Many thanks,
lifecrisis
EDIT -- Update and Lessons Learned:
The following list is a summary of all of the relevant facts and interpretations that explain why the third loop does not work like the first two.
s is a separate variable holding a copy of the value (a pointer-to-char) from the variable family2[0]. I.e., these two equivalent values are positioned at SEPARATE locations in memory.
family2[0] up to family2[3] are contiguous elements of memory, and s has no presence in this space, though it does contain the same value that is stored in family2[0] at the start of our loop.
These first two facts mean that &s and &family2[0] are NOT equal. Thus, adding one to &s will return a pointer to unknown/undefined data, whereas adding one to &family2[0] will give you &family2[1], as desired.
In addition, the update step in the third for loop doesn't actually result in s stepping forward in memory on each iteration. This is because &s is constant throughout all iterations of our loop. This is the cause of the observed infinite loop.
Thanks to EVERYONE for their help!
lifecrisis
When you do s = *(&s + 1) the variable s is a local variable in an implicit scope that only contains the loop. When you do &s you get the address of that local variable, which is unrelated to any of the arrays.
The difference from the previous loop is that there s is a pointer to the first element in the array.
To explain it a little more "graphically" what you have in the last loop is something like
+----+ +---+ +------------+
| &s | ---> | s | ---> | family2[0] |
+----+ +---+ +------------+
That is, &s is pointing to s, and s is pointing to family2[0].
When you do &s + 1 you effectively have something like
+------------+
| family2[0] |
+------------+
^
|
+---+----
| s | ...
+---+----
^ ^
| |
&s &s + 1
Pictures help a lot:
+----------+
| "father" |
+----------+ +----------+ +-------+ NULL
/-----------→1000 | "mother" | | "son" | ↑
+-----+ ↑ +----------+ +-------+ |
| s | ? | 2000 2500 |
+-----+ | ↑ ↑ |
6000 6008 +----------------+----------------+--------------+--------------+
| family2[0] | family2[1] | family2[2] | family2[3] |
+----------------+----------------+--------------+--------------+
5000 5008 5016 5024
( &s refers to 6000 )
( &s+1 refers to 6008 but )
( *(&s+1) invokes UB )
Addresses chosen as random integers for simplicity
The thing here is that, although both s and family2[0] point to the same base address of the string literal "father", the pointers aren't related with each other and has its own different memory location where they are stored. *(&s+1) != family2[1].
You hit UB when you do *(&s + 1) because &s + 1 is a memory location you're not supposed to tamper with, i.e, it doesn't belong to any object you created. You never know what's stored in there => Undefined Behavior.
Thanks #2501 for pointing out several mistakes!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char* string;
int main() {
char *family1[4] = { "father", "mother", "son", NULL };
string family2[4] = { "father", "mother", "son", NULL };
/* Loop #1: Using a simple pointer to step through "family1". */
for (char **p = family1; *p != NULL; p++) {
printf("%s\n", *p);
}
putchar('\n');
/* Loop #2: Using the typedef for clarity and stepping through
* family2. */
for (string *s = family2; *s != NULL; s++) {
printf("%s\n", *s);
}
putchar('\n');
/* Loop #3: Again, we use the pointer, but with a unique increment
* step in our for loop. This fails to work. Why? */
/*for (string s = family2[0]; s != NULL; s = *(&s + 1)) {
printf("%s\n", s);
}
*/
for (int j = 0; j < 3; j++)
{
printf("%d ",family2[j]);
printf("%d\n", strlen(family2[j]));
}
printf("\n");
int i = 0;
for (string s = family2[i]; i != 3; s = (s + strlen(family2[i]) + 2),i++) {
printf("%d ",s);
printf("%s\n", s);
}
system("pause");
}
this is a example revised from your code,if you run it,you will find the change of the address of the point and the family2, then you will understand the relationship of the loop #3.

Seg fault when using structure pointers to access struct members in C

What is wrong with my program, I get seg fault when I try to print the values.
My aim is assign some values in sample_function.
and in main function I want to copy the structure to another structure.
#include<stdio.h>
#include<string.h>
typedef struct
{
char *name;
char *class;
char *rollno;
} test;
test *
sample_function ()
{
test *abc;
abc = (test *)malloc(sizeof(test));
strcpy(abc->name,"Microsoft");
abc->class = "MD5";
abc->rollno = "12345";
printf("%s %s %s\n",abc->name,abc->class,abc->rollno);
return abc;
}
int main(){
test *digest_abc = NULL;
test *abc = NULL;
abc = sample_function();
digest_abc = abc;
printf(" %s %s %s \n",digest_abc->name,digest_abc->class,digest_abc->rollno);
return 1;
}
Pointer has always been a nightmare for me, I never understood it.
test * sample_function ()
{
test *abc;
strcpy(abc->name,"Surya");
What do you think abc points to, here? The answer is, it doesn't really point to anything. You need to initialize it to something, which in this case means allocating some memory.
So, let's fix that first issue:
test * sample_function ()
{
test *abc = malloc(sizeof(*abc));
strcpy(abc->name,"Surya");
Now, abc points to something, and we can store stuff in there!
But ... abc->name is a pointer too, and what do you think that points to? Again, it doesn't really point to anything, and you certainly can't assume it points somewhere you can store your string.
So, let's fix your second issue:
test * sample_function ()
{
test *abc = malloc(sizeof(*abc));
abc->name = strdup("Surya");
/* ... the rest is ok ... */
return abc;
}
Now, there's one last issue: you never release the memory you just allocated (this probably isn't an issue here, but it'd be a bug in a full-sized program).
So, at the end of main, you should have something like
free(abc->name);
free(abc);
return 1;
}
The final issue is a design one: you have three pointers in your structure, and only convention to help you remember which is dynamically allocated (and must be freed) and which point to string literals (and must not be freed).
That's fine, so long as this convention is followed everywhere. As soon as you dynamically allocate class or rollno, you have a memory leak. As soon as you point name at a string literal, you'll have a crash and/or heap damage.
As japreiss points out in a comment, a good way to enforce your convention is to write dedicated functions, like:
void initialize_test(test *obj, const char *name, char *class, char *rollno) {
obj->name = strdup(name);
...
}
void destroy_test(test *obj) {
free(obj->name);
}
test *malloc_test(const char *name, ...) {
test *obj = malloc(sizeof(*obj));
initialize_test(obj, name, ...);
return test;
}
void free_test(test *obj) {
destroy_test(obj);
free(obj);
}
In your function sample_function you return a pointer to abc. You cannot do this in C due to the way Activation Records are organized.
An Activation Record is a data structure that contains all the relevant information for a function call, parameters, return address, addresses of local variables, etc...
When you call a function a new Activation Record gets pushed onto the stack it could look something like this.
// Record for some function f(a, b)
| local variable 1 | <- stack pointer (abc in your case)
| local variable 2 |
| old stack pointer | <- base pointer
| return address |
| parameter 1 |
| parameter 2 |
---------------------
| caller activation |
| record |
When you return from a function this same activation record gets popped off of the stack but what happens if you returned the address of a variable that was on the old record ?
// popped record
| local variable 1 | <- address of abc #
| local variable 2 | #
| old stack pointer | # Unallocated memory, any new function
| return address | # call could overwrite this
| parameter 1 | #
| parameter 2 | #
--------------------- <- stack pointer
| caller activation |
| record |
Now you try to use abc and your program correctly crashes because it sees that you are accessing an area of memory that is unallocated.
You also have problems with allocation, but other answers have already covered that.
In sample_function you declare abc as a pointer to a test structure, but you never initialize it. It's just pointing off into the weeds somewhere. Then you try to dereference it to store values - BOOM.
Your program doesn't need any pointers at all; structures can be passed by value in C.
If you do want to keep similar interfaces to what you have now, you're going to have to add some dynamic allocations (malloc/free calls) to make sure your structures are actually allocated and that your pointers actually point to them.

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