I have the following code which simply prints out an introduction for a person's name.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char* firstname;
char* lastname;
}Person;
void intro(void *person){
printf("The person you are looking for is %s %s\n", ((Person *)person)->firstname, ((Person *)person)->lastname);
}
int main()
{
Person *a = NULL;
a = (Person *)malloc(sizeof(Person));
char *first = NULL, *last = NULL;
first = (char *)malloc(sizeof(char)*20);
strncpy(first,"Bob", 20);
last = (char *)malloc(sizeof(char)*20);
strncpy(last,"Newmonson", 20)
a->firstname = first;
a->lastname = last;
intro(a);
return 0;
}
Produces the output
The person you are looking for is Bob Newmonson
However changing intro(a) to intro(&a) produces
The person you are looking for is �# Newmonson
When I open the first attempt in GDB and break on line 10 I find the address of person=0x601010. Both the first name and last name are stored where I would expect, 0x04006b9 and 0x4006bd since they where declared earlier in the stack.
What gets me is when I run GDB with the changes made to intro(&a). The address of person is now 0x7fffffffffdd38, with the first name pointing to 0x601010 and the last name pointing to 0x4006db.
Can anyone help explain to be what is going on and why I can still access the proper address of the last name in the second test.
EDIT :
As everyone seems to keep asking about it the void * was for a threading portion of this code that I did not include.
It's because a is already pointer to a Person structure; therefore intro(&a) passes a pointer to that pointer, but intro() treats it's argument as a pointer to Person.
Also, if intro() is intended to work on a Person, it should declare a Person * argument, not a void *.
The address being held inside of the pointer variable a is not the same as the address of the actual memory location being taken up by a.
And address like 0x601010 is a "low" memory address, and is going to typically be somewhere on the heap. An address like 0x7fffffffffdd38 is a very "high" address, and will typically be on the stack. So &a is giving you the actual address of the variable a on the stack, and it is passing that value to the function, not the value 0x601010 being stored inside the pointer variable a, and representing the first address of the allocated memory buffer returned from malloc.
First of all:
/* allocate space for 20 characters and make 'first' point to that space. */
first = (char *)malloc(sizeof(char)*20);
/* now make 'first' point to the string Bob. Leak the memory that was allocated before. */
first = "Bob";
/* Rinse, lather, repeat. */
last = (char *)malloc(sizeof(char)*20);
last = "Newmonson";
Now to explain why using intro(&a) gives you unexpected results:
intro expects a pointer, which it assumes points to a structure of type Person. You create a pointer to a Person and then allocate space for it.
Calling intro(a) causes the pointer to Person to be passed as a pointer to void to intro, which then treats it as a pointer to Person and all is well.
Calling intro(&a) however takes the address of a and passes that in. Again, intro tries to treat it as a pointer to Person but that won't work because what you've passed is a pointer to a pointer to a Person. You're passing tomatoes to a function that thinks it's getting oranges. Both are fruit, and you will get juice, although you are probably not going to to be very happy when your breakfast is served with delicious tomato juice instead of delicious orange juice.
If you are asking why calling intro(&a) causes the first name to be mangled but the last name to be printed, the answer is because of sheer luck: the string with the last name just happened to be in the right position in memory.
try this:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char* firstname;
char* lastname;
}Person;
void intro(Person *person){
printf("The person you are looking for is %s %s\n", (person)->firstname, (person)->lastname);
}
int main()
{
Person *a = NULL;
char *first = NULL, *last = NULL;
a = (Person *)malloc(sizeof(Person));
first = (char *)malloc(sizeof(char)*20);
first = "Bob";
last = (char *)malloc(sizeof(char)*20);
last = "Newmonson";
a->firstname = first;
a->lastname = last;
intro(a);
return 0;
}
hope it helps...
Related
I am working on an assignment and ran into challenging problem. As far as I'm concerned and from what I've learnt the code that follows should be correct however it does not work. Basically what I am trying to is copy a string value into the variable member of a structure the is part of an array passed into a method as a pointer. What am I missing?
typedef struct
{
char * name; //variable in struct I am trying to access
} Struct;
void foo(Struct * arr) //array of Structs passed into function as a pointer
{
int i = 0;
while(i++ < 2)
{
arr[i].name = malloc(sizeof(char *)); //assigning memory to variable in each Struct
arr[i].name = strdup("name"); //copying "name" to variable in each Struct
printf("C - %s\n", arr[i].name); //printing out name variable in each Struct
}
}
main()
{
Struct * arr; //defining pointer
arr = calloc(2, sizeof(Struct)); //allocating memory so pointer can hold 2 Structs
foo(arr); //calling function foo passing pointer into function
return 0;
}
This code compiles and runs however it does not do what it is designed to do. Forgive me if it is something trivial. I am new to the language C
Two issues:
while(i++ < 2) This line changes the value of i as soon as it checks it, so your loop body will not be the same as it was checked.
arr[i].name = strdup("name"); overwrites the value of the .name pointer, causing a memory leak of the memory you malloc()'ed earlier.
Extending on 2 pointed out correctly already,
arr[i].name = strdup("name");
Even if you use following instead of above,
strcpy(array[i].name, "name");
you haven't allocated enough bytes to store the string i.e. this is wrong
arr[i].name = malloc(sizeof(char *));
// even if pointer is 8 byte here, concept isn't right
Should be something like
arr[i].name = malloc(strlen("name")+1);
// or MAX_SIZE where it is greater than the possible "name".
Or better yet, remove the malloc at all, strdup takes care of allocation itself
This is not answering your question directly, but addresses an issue to big to put into a comment...
Additional issue: You probably did not intend to allocate only a (char *) worth of memory to a variable intended to hold at least "name". Change;
arr[i].name = malloc(sizeof(char *));
to:
arr[i].name = malloc(sizeof(char)*strlen("name")+1); //+1 for '\0'
or better yet, use char *name="name";, then:
arr[i].name = malloc(sizeof(char)*strlen(name)+1);
Even more general (and better):
char *name;
name = malloc(strlen(someInputString)+1);
//do stuff with name...
free(name);
Now, you can allocate name to any length needed based on the length of someInputString.
[EDIT]
Etienz, I wanted to address one more thing, alluded to by #H2CO3 above, but not really explained, that I think might be useful to you:
Regarding your desire to have room for two structs, because you typedef'd your struct, you can simply do something like this: (but I am going to change the name you used from Struct to NAME :) The whole point being that when a struct is created as an array, you do not need to use calloc or malloc to create space for them, it is done as shown below...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char *name;
}NAME;
//use new variable type NAME to create global variables:
NAME n[2], *pN; //2 copies AND pointer created here
//prototype func
int func(NAME *a);
int main()
{
pN = &n[0]; //pointer initialized here
func(pN); //pointer used here (no malloc or calloc)
printf("name1 is %s\nname 2 is %s", pN[0].name, pN[1].name);
return 0;
}
int func(NAME *a)
{
char namme1[]="andrew";
char namme2[]="billebong";
//You DO have to allocate the members though
a[0].name = malloc(strlen(namme1)+1);
a[1].name = malloc(strlen(namme2)+1);
strcpy(a[0].name, namme1);
strcpy(a[1].name, namme2);
return 0;
}
i'm obviously not blaming printf here, i probably messed up my mem allocations and access but i can't understand where i did wrong. the program crash on the second printf in main. It also crash on the third if i comment the second one. Actually it crash whenever i access p after the first printf !
Can someone explains me what i am doing wrong ?
Thanks a lot.
typedef struct
{
char * firstname;
char * lastname;
int age;
} person;
person * new_person(char * firstname, char * lastname, int age)
{
person p;
int lf = strlen(firstname);
int ll = strlen(lastname);
p.firstname = (char *)malloc(++lf * sizeof(char));
p.lastname = (char *)malloc(++ll * sizeof(char));
strcpy(p.firstname, firstname);
strcpy(p.lastname, lastname);
p.age = age;
return &p;
}
int main()
{
person * p = new_person("firstname", "last", 28);
printf("nom : %s ; prenom : %s ; age : %d\n", p->lastname, p->firstname, p->age);
printf("nom : %s ; prenom : %s ; age : %d\n", p->lastname, p->firstname, p->age);
printf("nom : %s ; prenom : %s ; age : %d\n", (*p).lastname, (*p).firstname,(*p).age);
return 0;
}
You're returning the address of a local variable.
You can either modify your new_person to take an argument (a pointer to a person) or you can malloc one inside the function and manipulate that.
The person you declared in your function goes out of scope when the function returns. Everything that happens to it after that is undefined. It might coincidentally keep its value for a while, but you should not depend on this. When you make your call to printf, the stack grows and overwrites the old location of your person with new stuff.
I think the issue is in this line:
return &p;
Notice that you are returning a pointer to a local variable. This results in undefined behavior, since as soon as the function returns, the local variable p no longer exists. As a result, reading or writing that pointer will read or write garbage data.
The fact that this doesn't immediately crash is an artifact of how the compiler generates code. Chances are, the first time you call printf, it reuses space that was previously used for p in a way that, by sheer coincidence, works out fine. However, after the function returns, its stack frame has clobbered the old memory for p. As a result, the second call to printf is reading garbage data left behind from the call to printf, hence the crash.
(Specifically: when you pass the parameters, it copies the pointers to the strings onto the stack, so when printf runs, it's probably trashing the original pointers, but using the copies. The second call then loads garbage pointers from the expired printf stack frame, since it lives at the same address that p used to live in.)
To fix this, consider changing p to a pointer to a person and then using malloc to allocate it. That way, the memory persists beyond the function call, so this crash should go away.
Hope this helps!
person p;
// stuff
return &p
This is wrong. After the function returns, the local variable is leaving the scope - its address will be invalid. You have to allocate the structure on the heap:
person *new_person(char *firstname, char *lastname, int age)
{
person *p = malloc(sizeof(*p));
p->firstname = strdup(firstname);
p->lastname = strdup(lastname);
p->age = age;
return p;
}
The problem is in the function new_person. You create person p on the stack and return its address. You need to allocate person* p = new person(.....
I have some odd behaviour going on in my code which seems to be resulting from the use of a generic pointer though really I am totally uncertain. I have a fairly standard struct which looks like the following:
typedef struct {
char* name;
PyAutoCFunc ac_func;
void (*func)();
PyAutoType type_id;
int num_args;
PyAutoType arg_types[MAX_ARG_NUM];
} func_entry;
static func_entry* func_entries;
I am storing a static pointer to an array of these struct elements which is allocated on the heap. At the point where I create a new element of this array and insert it, its values look like this...
func_entry new_fe;
new_fe.name = malloc(strlen(name) + 1);
strcpy(new_fe.name, name);
... // Init rest of struct
func_entries[num_func_entries] = new_fe;
num_func_entries++;
func_entry* fe = &func_entries[num_func_entries-1];
printf("Setting function '%s' at address '%p', name address '%p'\n", name, fe, fe->name);
This outputs.
>>> Setting function 'graphics_viewport_set_title' at address '0xfe2d40', name address '0xe40fe0'
Notice the size and value of fe->name. I then store this pointer into a hashtable to retrieve later. In the hashtable this is stored as a simple void*. Later when I retrieve the pointer from the hashtable an odd thing happens.
func_entry* fe = PyAutoHashtable_Get(func_table, c_func_name);
printf("Getting function '%s' at address '%p', name address '%p'\n", c_func_name, fe, fe->name);
Which outputs.
>>> Getting function 'graphics_viewport_set_title' at address '0xfe2d40', name address '0x6e6f74656c656b73'
The address of fe has clearly been in and out of the hashtable without issue, but the size and address of fe->name has changed. Even more weirdly is that fe->name is a different size to what it was before and even a different size to fe. Trying to access fe->name gives me a segfault and I am unsure how to proceed.
Out of interest this seems to occur when I use the code in an application with several linked libraries, I'm fairly sure all the code I'm running is 64 bit.
I have run the above code successfully in a separate application and get a correct pointer for fe->name (a smaller one).
I am also running on Ubuntu Linux 64 bit and compiling with gcc.
This is really where my C ignorance shines though as I imagine it could be a million things. Can anyone shine some light?
That address for name looks like the result of memory corruption. It's completely unaligned, which is unlikely for an address returned by strdup off the heap.
It looks like you're out of scope for the structure you created. You mentioned it's created on the heap, but in the code it looks like it's probably created on the stack. This isn't all being done in the same function, is it? Is the code in the first block in a function that's existed before running the code in the later block? As soon as you exit that function the memory for that structure ceased to be, even though you retained a pointer to it. Later, when you pulled the pointer out of the hash table the memory had been overwritten and didn't have the pointer to name there anymore. If you're going to pass around pointers to structures allocate them dynamically by using malloc. They're exist until you explicitly get rid of them using free, instead of when the function ends.
Pointers always are of the same size whether its a pointer to a struct or a generic pointer (char * in olden days, void * in ANSI standard.)
Here's a simple example I whipped out so that you could understand structures, pointers (not in detail though but you get the idea.)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct person {
char *name;
int age;
};
void print(void *);
int main()
{
struct person *david;
if ((david = (struct person *)malloc(sizeof(struct person))) != NULL) {
david->name = strdup("David");
david->age = 40;
printf("sizeof david = %d, sizeof person = %d\n", sizeof david,
sizeof(struct person));
print((void *)david);
}
}
void print(void *p)
{
struct person *pp = (struct person *)p;
printf("sizeof p = %d, sizeof pp = %d\n%s %d\n", sizeof p, sizeof pp,
pp->name, pp->age);
}
Output
sizeof david = 8, sizeof person = 16
sizeof p = 8, sizeof pp = 8
David 40
Hope that helps.
It certainly looks as if something is writing over that data structure. The pointer value 0x6e6f74656c656b73 which you are seeing looks very suspicious indeed - it is ASCII for "noteleks", which is "skeleton" backwards. Perhaps this might give you an idea of what is overwriting your data.
i use pointer for holding name and research lab property. But when i print the existing Vertex ,when i print the vertex, i cant see so -called attributes properly.
For example though real value of name is "lancelot" , i see it as wrong such as "asdasdasdasd"
struct vertex {
int value;
char*name;
char* researchLab;
struct vertex *next;
struct edge *list;
};
void GRAPHinsertV(Graph G, int value,char*name,char*researchLab) {
//create new Vertex.
Vertex newV = malloc(sizeof newV);
// set value of new variable to which belongs the person.
newV->value = value;
newV->name=name;
newV->researchLab=researchLab;
newV->next = G->head;
newV->list = NULL;
G->head = newV;
G->V++;
}
/***
The method creates new person.
**/
void createNewPerson(Graph G) {
int id;
char name[30];
char researchLab[30];
// get requeired variables.
printf("Enter id of the person to be added.\n");
scanf("%d",&id);
printf("Enter name of the person to be added.\n");
scanf("%s",name);
printf("Enter researc lab of the person to be added\n");
scanf("%s",researchLab);
// insert the people to the social network.
GRAPHinsertV(G,id,name,researchLab);
}
void ListAllPeople(Graph G)
{
Vertex tmp;
Edge list;
for(tmp = G->head;tmp!=NULL;tmp=tmp->next)
{
fprintf(stdout,"V:%d\t%s\t%s\n",tmp->value,tmp->name,tmp->researchLab);
}
system("pause");
}
When you do this:
newV->name=name;
newV->researchLab=researchLab;
You are copying the pointer to the strings name and researchLab. You are not copying the strings themselves. In other words, after this, newV->name and name point to exactly the same location in memory where the name is stored; you have not created a duplicate copy of the data.
Since you then proceed to overwrite the name array in the createNewPerson function, at the end of this function, all of your vertex structs will have their name attribute pointing to the same memory location, which is only storing the last name entered.
Worse, when createNewPerson returns, its local name array goes out of scope, and is re-used for other things. Since your vertex structs are still pointing here for their name attributes, this is how you get garbage.
You need to duplicate the string. A simple way to do it is:
newV->name = strdup(name);
You will need to #include <string.h> to get the strdup library function.
And then you also need to make sure that you call free on the name attribute whenever you are disposing of a vertex structure.
GRAPHinsertV copies the pointer of the name and researchLab strings to the vector structure.
createNewPerson creates a temporary for the name and researchLab strings.
The problem here is, you're pointing to a temporary string which causes undefined behaviour when you access it after createNewPerson returns.
To solve this problem, you can duplicate the strings in GRAPHinsertV using malloc+strcpy, or by using the non-standard strdup.
The name variable you pass to GRAPHinsertV() is allocated on the stack for createNewPerson(), so the pointer points to a local variable. Once the activations records are popped off that value can (and will) be overwritten by subsequent code.
You need to allocate memory on the heap if you are only going to keep a char * in the struct.
Ex. Instead of
char name[30];
you could use
char *name = (char *)malloc(30*sizeof(char));
but keep in mind if you manually allocate it you have to take care of freeing it as well, otherwise it will have a memory leak.
When you assign the char *name pointer, like
newV->name=name;
You're not creating a new string, but making the newV.name member point to the same memory as the char[] array that was passed in. You'll need to malloc() or otherwise allocate a new char[] array in order to obtain separate storage for each structure.
There's a problem here:
Vertex newV = malloc(sizeof newV);
It should be
Vertex *newV = malloc(sizeof(Vertex));
You are allocating memory in the function createNewPerson() that lasts exactly as long as createNewPerson() is executing, and is available for overwriting immediately after it returns. You need to copy the text fields in with something like strdup(newV->name, name), rather than point to the local variables in createNewPerson(). (If your implementation doesn't have strdup(), you can easily define it as:
char * strdup(const char *inp)
{
char * s = malloc(strlen(inp) + 1);
strcpy(s, inp);
return s;
}
In addition, your I/O has potential problems. If you enter my name, "David Thornley", for the name, it'll take "David" as the name and "Thornley" as the lab, since "%s" searches for a whitespace-delimited string. If I enter "Forty-two" for the ID, nothing will be put in id, and "Forty-two" will be used for the name. If I enter a name or lab name over 29 characters, it will overwrite other memory.
I'd suggest using fgets() to get one line of input per answer, then use sscanf() to parse it.
When passing and assigning strings, always make a copy of them. There're no guarantees that the string you received is still in the memory afterwards, since the pointer could have been freed.
Of course, if you are only going to use name inside the function (that's, you're not going to assign it to a variable outside the scope of the function), you don't have to do the copy.
In order to do that, inside GRAPHinsertV, instead of
newV->name=name;
do
if (name != NULL) // Preventing using null pointer
{
newV->name = malloc(strlen(name)+1);
strcpy(newV->name, name);
}
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 = #
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 = #
// 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 :)