C memory allocation for struct with malloc - c

I am trying to understand the memory allocation in C for struct but I am stuck on it.
struct Person {
char *name;
int age;
int height;
int weight;
};
struct Person *Person_create(char *name, int age, int height, int weight)
{
struct Person *who = malloc(sizeof(struct Person));
assert(who != NULL);
who->age = age;
who->height = height;
who->weight = weight;
who->name = strdup(name);
return who;
}
int main(int argc, char *argv[])
{
struct Person *joe = Person_create("ABC", 10, 170, 60);
printf("Size of joe: %d\n", sizeof(*joe));
printf("1. Address of joe \t= %x\n", joe);
printf("2. Address of Age \t= %x\n", &joe->age);
printf("3. Address of Height \t= %x\n", &joe->height);
printf("4. Address of Weight \t= %x\n", &joe->weight);
printf("5. Address of name \t= %x\n", joe->name);
...
What I don't understand is the memory allocation for this struct. On my printout I see this:
Size of joe: 24
1. Address of joe = 602010
2. Address of Age = 602018
3. Address of Height = 60201c
4. Address of Weight = 602020
5. Address of name = 602030
Questions:
Why there is a gap between the 1 and 2?
Why there is a gap between the 4 and 5?
How is the size of *name being calculated as the name points only to
first char?

There is no gap between the address of the object joe and the address of data member age. This extent is occupied by data member name.
struct Person {
char *name;
int age;
//...
According to the output
1. Address of joe = 602010
2. Address of Age = 602018
it occupies 8 bytes that is sizeof( char * ) in your platform is equal to 8. And its address coincides with the address of the object joe itself.
In this statement
printf("5. Address of name \t= %x\n", joe->name);
you did not output the address of name itself. You printed the value stored in this pointer and this value is the address of the first character of a copy of the string literal "ABC" that was gotten by using strdup.
So there is a gap between values in the outputs 4 and 5 because they are different extents of memory. Data member weight belongs to object joe while the copy of the string literal "ABC" is stored outside the object. The object just has data member name that points to the first character of the copy of the literal.
As name is a pointer then its size is calculated like
sizeof( char * )
or
sizeof( joe->name )
and equal to 8 as I explained in the beginning of the post.
If you want to determine the length of the string literal you should use standard function strlen declared in header <string.h>. For example
printf( "%zu\n", strlen( joe->name ) );

Why there is a gap between the 1 and 2?
A struct's start address is always equal to the address of it's first member. From the C standard:
6.7.2.1-13. A pointer to a structure object, suitably converted, points to its initial member
The first member is not age, but name. So the following two lines should print the same address:
printf("1. Address of joe \t= %x\n", joe);
printf("1. Address of name-pointer \t= %x\n", &joe->name);
In your code,
printf("5. Address of name \t= %x\n", joe->name);
does not print the address of the pointer, but the address of the data the pointer points to.
How the size of *name is being calculated as the name points only to first char?
nameis a pointer, which occupies 8 bytes of memory regardless of the size of data it points to (that may be a string as in your case, a single char, an int or whatever).
Why there is a gap between the 4 and 5?
The memory for storing the actual name string is not within the struct - strdup allocates memory somewhere to duplicate the string into. This happens to be 16 bytes after the last member of your struct. This memory location is then pointed to by your name pointer.
Note that padding and memory alignment are a factor only for the size of the struct (they do not matter for your explicitly stated questions). Since the struct contains one pointer (8 bytes on your machine) and 3 integers (4 bytes each), one would assume that the total size is 20 bytes. On most platforms, memory is 8 byte aligned - which is why the size of your struct is rounded up to 24 bytes. This way, if you declare an array of Persons, each array element starts at an address that is 8 byte aligned, i.e., the address value can be divided evenly by 8.

The only things the c standard guarantees is that the address of the first member is the same as the address of the structure, and that the addresses of subsequent members increases with their position in the structure.
Compilers are allowed to insert spaces between members; this is called padding. Regard it as the compiler optimising the structure for a particular platform.
Arrays must always be contiguous in memory though.

It is due to something called Data alignment. To quote from this website
Every data type in C/C++ will have alignment requirement (in fact it is mandated by processor architecture, not by language).
And then extending this requirement for structures:
Because of the alignment requirements of various data types, every member of structure should be naturally aligned.
You can go through this article for a detailed read..

The memory layout of the struct is machine dependent, so you should not bother with that unless you are trying to implement a DBMS or a device driver or something like that.
sizeof(*name) would equal to sizeof(char), I do not get what confused you here, can you give further explanation?

Related

Some confusions about struct memory allocation mechanism?

During my project, I am confronted with C program.
As shown below, htmp is a struct pointer. We first allocate a memory for it. But why should we allocate a memory for its element word again?
If it's essential to allocate memory for each element of a struct, why not allocate memory for its other elements, id and next?
#define HASHREC bitewisehash
typedef struct hashrec {
char *word;
long long id;
struct hashrec *next;
} HASHREC;
/* Move-to-front hashing and hash function from Hugh Williams, http://www.seg.rmit.edu.au/code/zwh-ipl/ */
/* Simple bitwise hash function */
unsigned int bitwisehash(char *word, int tsize, unsigned int seed) {
char c;
unsigned int h;
h = seed;
for (; (c =* word) != '\0'; word++) h ^= ((h << 5) + c + (h >> 2));
return((unsigned int)((h&0x7fffffff) % tsize));
}
/* Insert string in hash table, check for duplicates which should be absent */
void hashinsert(HASHREC **ht, char *w, long long id) {
HASHREC *htmp, *hprv;
unsigned int hval = HASHFN(w, TSIZE, SEED);
for (hprv = NULL, htmp = ht[hval]; htmp != NULL && scmp(htmp->word, w) != 0; hprv = htmp, htmp = htmp->next);
if (htmp == NULL) {
htmp = (HASHREC *) malloc(sizeof(HASHREC)); # allocate memory for htmp
htmp->word = (char *) malloc(strlen(w) + 1); # why allocate memory again ?
strcpy(htmp->word, w); #
htmp->id = id; # why not allocate memory for htmp->id ?
htmp->next = NULL; # why nor allocate memory for htmp->next?
if (hprv == NULL) ht[hval] = htmp;
else hprv->next = htmp;
}
else fprintf(stderr, "Error, duplicate entry located: %s.\n",htmp->word);
return;
}
You need to separate in your mind two things (1) in what memory is the thing I want to store stored?; and (2) what variable (pointer) holds the address to where it is stored so I can find it again.
You first declare two pointers to struct hashrec:
HASHREC *htmp, *hprv;
A pointer is nothing but a variable that holds the address to something else as its value. When you first declare the two pointers, they are uninitialized and hold no address. You then, in a rather awkward manner, initialize both pointers within a for loop declaration, e.g. hprv = NULL, htmp = ht[hval] and later hprv = htmp, htmp = htmp->next so presumably both pointers now hold an address and point somewhere.
Following the loop (with an empty body), you test if (htmp == NULL), meaning that htmp does not point to an address (which can be the case if you have found the hash-index of interest empty).
Then in order to provide storage for one HASHREC (e.g. a struct hashrec) you need to allocate storage so you have a block of memory in which to store the thing you want to store. So you allocate a block to hold one struct. (See: Do I cast the result of malloc?)
Now, look at what you have allocated memory for:
typedef struct hashrec {
char *word;
long long id;
struct hashrec *next;
} HASHREC;
You have allocated storage for a struct that contains (1) a char *word; (a pointer to char - 8-bytes (4-bytes on x86)); (2) a long long id; (8-bytes on both) and (3) a pointer to hold the address of the next HASHREC in the sequence.
There is no question that id can hold a long long value, but what about word and next? They are both pointers. What do pointers hold? The address to where the thing they point to can be found. Where can word be found? The thing you want is currently pointed to by w, but there is no guarantee that w will continue to hold the word you want, so you are going to make a copy and store it as part of the HASHREC. So you see:
htmp->word = malloc(strlen(w) + 1); /* useless cast removed */
Now what does malloc return? It returns the address to the beginning of a new block of memory, strlen(w) + 1 bytes long. Since a pointer holds the value of something else as its value, htmp->word now stores the address to the beginning of the new block of memory as its value. So htmp->word "points" to the new block of memory and you can use htmp->word as a reference to refer to that block of memory.
What happens next is important:
strcpy(htmp->word, w); #
htmp->id = id; # why not allocate memory for htmp->id ?
htmp->next = NULL; # why nor allocate memory for htmp->next?
strcpy(htmp->word, w); copies w into that new block of memory. htmp->id = id; assigns the value of id to htmp->id and no allocation is required because when you allocate:
htmp = malloc(sizeof(HASHREC)); /* useless cast removed */
You allocate storage for a (1) char * pointer, (2) a long long id; and (3) a struct hashrec* pointer -- you have already allocated for a long long so htmp->id can store the value of id in the memory for the long long.
htmp->next = NULL; # why nor allocate memory for htmp->next?
What is it that you are attempting to store that would require new allocation for htmp->next? (hint: nothing currently) It will point to the next struct hashrec. Currently it is initialize to NULL so that the next time you iterate to the end of all the struct hashrec next pointers, you know you are at the end when you reach NULL.
Another way to think of it is that the previous struct hashrec next can now point to this node you just allocated. Again no additional allocation is required, the previous node ->next pointer simply points to the next node in sequence, not requiring any specific new memory to be allocated. It is just used as a reference to refer (or point to) the next node in the chain.
There is a lot of information here, but when you go through the thought process of determining (1) in what memory is the thing I want to store stored?; and (2) what variable (pointer) holds the address to where it is stored so I can find it again... -- things start to fall into place. Hope this helps.
When you allocate the memory for the struct, only enough memory to hold a pointer is allocated for the member word, that pointer also has to point to valid memory which you can then allocate.
Without making it point to valid memory, it's value is indeterminate and trying to dereference such pointer with an indeterminate value is undefined behavior.
malloc(size) will allocate memory of given size and returns starting address of the allocated memory. Addresses are stored in pointer variables.
In char *word, variable word is of pointer type and it can only hold a pointer of type char i.e., address of a character data in memory.
so, when you allocate memory to the struct type variable htmp, it will allocate memory as follows, 2 bytes for *word, 4 bytes for id and 2 bytes for *next
Now, lets assume that you want to store following into your struct:
{
word = Elephant
id = 1245
}
Now you can save id directly into id member by doing this htmp->id = 1245. But you also want to save a word "Elephant" in your struct, how to achieve this?
htmp->word = 'Elephant' will cause error because word is a pointer. So, now you allocate memory to store actual string literal Elephant and store the starting address in htmp->word.
Instead of using char *word in your struct, you could have used char word[size] where no need to allocate memory separately for member word. The reason behind not doing so, is that you want to select some random size for word, which can waste memory if you are storing less characters and which even fall shot if word is too big.

accessing elements of dynamiclly allocated array

I'm trying to access the next element in dynamically allocated by adding the size of placeholder array to the first element. Size of placeholder array is 4 bytes, so if I add 4 bytes to it first element with address 2147549788, I should be looking at next memory location 2147549792. But, instead I'm looking at an address in 16 bytes 2147549804. If I read the address of array elements directly I get the right address. Wondering why adding size of placeholder gives different results ?
Also, if I access the location of second element outside the for loop, the location is off by another 16 bytes i.e 2147549820
#include "stdio.h"
#include "time.h"
#include <stdlib.h>
#include <string.h>
typedef struct Section {
int numOfStudents;
} Section;
typedef struct School {
int schoolId;
Section sections[1]; //placeholder
} School;
int main(void)
{
School *schoolA_p;
Section section1;
int sizeOffset = 0;
int i,sectionSize;
int sizeOfSchool = sizeof(School) - sizeof(Section) + (sizeof(Section)*2);
schoolA_p = (struct School *) malloc(sizeOfSchool);
for(i=0;i<2;i++)
{
sectionSize = sizeof(Section);
printf("\nsize of section = %d\n", sizeof(Section));
printf("Number of bytes to add to first element to access the next element = %d\n", sizeOffset);
printf("In Loop Location of schoolA_p->sections[%d]= 0x%lx\n",i, &(schoolA_p->sections[0]) + sizeOffset);
sizeOffset += sectionSize;
}
printf("\n Location of schoolA_p->sections[0]= 0x%lx\n",&(schoolA_p->sections[0]));
printf("\n Location of schoolA_p->sections[1]= 0x%lx\n",&(schoolA_p->sections[1]));
printf("\n Outside of lopop Location of schoolA_p->sections[0]= 0x%lx\n", &(schoolA_p->sections[0])+ sizeOffset);
free(schoolA_p);
return 0;
}
Pointer arithmetic works like this: If p is a pointer to an array element a[n], then p + i is a pointer to a[n + i]. In other words, pointer arithmetic moves in units of whatever base type the pointer is declared as, not bytes.
C pointer arithmetic takes into account the size of the data pointed to when you increment a pointer.
So if p is a pointer to data of 4 bytes, p + 1 calculates the address 4 bytes after p.
In other words, your doing too much work. C does this bookkeeping for you, and that's why you're getting incorrect results.
As a side note, this is why you cannot use pointer arithmetic on void* pointers. The size of the data pointed to is not specified.

Sizeof Structure in C [duplicate]

This question already has answers here:
Why isn't sizeof for a struct equal to the sum of sizeof of each member?
(13 answers)
Closed 8 years ago.
To find the size of a structure in C
struct student
{
char name;
int age;
float weight;
};
main ()
{
int i,j,k,l;
struct student s1;
i=sizeof(s1.name);
j=sizeof(s1.age);
k=sizeof(s1.weight);
l=sizeof(s1);
printf ("\n size of name %d",i);
printf ("\n size of age %d",j);
printf ("\n size of weight %d",k);
printf ("\n size of s1 %d",l);
printf("\n");
}
My output is:
size of name 1
size of age 4
size of weight 4
size of s1 12
But structure size should be the sum of sizes of its members. Why am i getting 12 instead of 9 as size of structure variable s1. Can someone explain what is wrong.
For performance or hardware reasons, fields in structures should be suitably aligned. Read about data structure alignment (details depend upon the target processor and the ABI).
In your example on x86-64/Linux:
struct student {
char name;
int age;
float weight;
};
the field name has no alignment requirement.
the field age needs 4 bytes aligned to a multiple of 4
the field weight needs 4 bytes aligned to a multiple of 4
so the overall struct student needs 12 bytes aligned to a multiple of 4
If weight was declared double it would need 8 bytes aligned to a multiple of 8, and the entire structure would need 16 bytes aligned to 8.
BTW, the type of your name field is wrong. Usually names are more than one single char. (My family name needs 13 letters + the terminating null byte, i.e. 14 bytes). Probably you should declare it a pointer char *name; (8 bytes aligned to 8) or an array e.g. char name[16]; (16 bytes aligned to 1 byte).
The GCC compiler provides a nice extension: __alignof__ and relevant type attributes.
If performance or size is important to you, you should put fields in struct in order of decreasing alignment requirements (so usually start with the double fields, then long and pointers, etc...)

Different Result than calculated,using the SIZEOF operator? [duplicate]

This question already has answers here:
Why isn't sizeof for a struct equal to the sum of sizeof of each member?
(13 answers)
Closed 8 years ago.
I was writing the code to check size of the int ,char and some struct.But its giving different result than manually calculated one.
#include<stdio.h>
struct person
{
int roll;
char name[10];
};
void main()
{
struct person p1;
printf("\n The size of the integer on machine is \t :: %d \n ",sizeof(int));
printf("\n The size of the char on machine is \t :: %d \n ",sizeof(char));
printf("\n The size of structre is \t :: %d \n",sizeof(struct person));
printf("\n The size of structre is \t :: %d \n",sizeof(p1));
}
I think structure shall have size = 10 * 1 + 4 = 14. But the output is
The size of the integer on machine is :: 4
The size of the char on machine is :: 1
The size of structre is :: 16
See what wikipedia says!
To calculate the size of any object type, the compiler must take into account any address alignment that may be needed to meet efficiency or architectural constraints. Many computer architectures do not support multiple-byte access starting at any byte address that is not a multiple of the word size, and even when the architecture allows it, usually the processor can fetch a word-aligned object faster than it can fetch an object that straddles multiple words in memory.[4] Therefore, compilers usually align data structures to at least a word alignment boundary, and also align individual members to their respective alignment boundaries. In the following example, the structure student is likely to be aligned on a word boundary, which is also where the member grade begins, and the member age is likely to start at the next word address. The compiler accomplishes the latter by inserting unused "padding" bytes between members as needed to satisfy the alignment requirements. There may also be padding at the end of a structure to ensure proper alignment in case the structure is ever used as an element of an array.
Thus, the aggregate size of a structure in C can be greater than the sum of the sizes of its individual members. For example, on many systems the following code will print 8:
struct student{
char grade; /* char is 1 byte long */
int age; /* int is 4 bytes long */
};
printf("%zu", sizeof (struct student));
You should try by altering the size of char array in your structure for better understanding
for example:
struct person
{
int roll;
char name[4];
};
Gives answer as 8
struct person
{
int roll;
char name[7];
};
Gives answer as 12
First you need to change %d to %zu because sizeof returns size_t type.
sizeof(p1) is giving 16 bytes instead of 14 because padding 2 bytes are added to it.
struct person
{
int roll; // 4 bytes
char name[10]; // 10 bytes. 2 bytes are needed for structure alignment
};

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