get the value from pointer to pointer in struct - c

I have a struct:
struct structname
{
structname** link;
int total;
}
I want to link structname1 to structname2. What I did was:
int *ptr = &structname2;
structname1 -> link = &ptr;
Then I tried to access the link for structname1 which is structname2:
structname *test = structname1 -> link;
Is this the correct way to do it? When I tried to print out, some unknown symbols printed. Can someone help me with this? Thanks.

You have to do in the below way.
struct structname structname1, structname2; //define two structures structname1 and structname2 of type structname.
struct structname * ptr; // ptr is a pointer to struct of type structname.
struct structname ** ptr2 // ptr2 is a double pointer to struct of type structname.
ptr = &structname2; // ptr points to structname2
ptr2 = &ptr; // ptr2 points to ptr and ptr points to structname2;
structname1.link = ptr2; // now link is a double pointer to structname2.
Let me correct if i'm wrong or missing

You have a couple of things wrong in your code. First, you got the type for ptr wrong: it should be struct structname ** instead of int *.
But if you're trying to do a linked list, you don't need the double indirection level at all. This is most likely what you want:
struct structname
{
struct structname *link;
int total;
}
With that, linking structname1 with structname2 is then as simple as (assuming structname1 and structname2 are of type struct structname):
struct structname *ptr = &structname2;
structname1.link = ptr;
If structname1 and structname2 are of type struct structname *, then you need this instead:
struct structname *ptr = structname2;
structname1->link = ptr;
You could also drop the intermediate variable ptr, it's not of much use here.

struct node {
struct node *next;
int cargo;
}
struct node *current, *last, *next;
unsigned char i;
current = (struct node*)(calloc(sizeof(struct node)));
for (last = current, unsigned char i = 5; i--;) {
next = (struct node*)(calloc(sizeof(struct node)));
next->cargo = i;
last->next = next;
}
The above code is a very easy linked list. Note that I changed a couple of things compared to your code. I create the objects using calloc, that means that the objects will be allocated on the heap instead of the stack. This also doesn't require you to have explicit names for every element, a.k.a. node in the linked list. It also means it won't be destroyed when you leve the scope of the names. Of course you will need to free all the nodes later, when you don't need the list anymore.
Then you don't need a pointer to a pointer in the node, a simple pointer is sufficient. In your main program you should also use an appropriate pointer. Even though, all pointers are the same size and can be cast into each other, you should - whenever possible - usde the right type.
Here I create another 5 nodes in a loop to demonstrate how 'flexible this approach is'.
If you want to do a circular linked list, that is quite easy as well. Simply append these line:
next->next = current;

Related

Creating a pointer directly from a typedef struct definition

I want to check what the following code means. I think I am creating a pointer to a list of pointers to adjlistnode structures but I'm not sure.
Here is the code:
typedef struct adjlistnode {int node; int cost; struct adjlistnode *next;}
**AdjMatrix;
I'm confused as to what **AdjMatrix actually is. Like I said above, I think it is a pointer to a list of pointers to adjlistnode structures but I'm not sure. Am I right in my assumption?
The rules around a typedef can be simplified to the following generalization: if you have any valid variable declaration in C (without a storage class such as extern, static or register, etc.), then strapping a typedef at the front turns the variable name into a new type name, based on the type of the variable.
So here, without the typedef:
struct adjlistnode {int node; int cost; struct adjlistnode *next;}
**AdjMatrix;
AdjMatrix is variable of type pointer to pointer to struct adjlistnode.
But in your post, because of the typedef, AdjMatrix is a name for the type pointer to pointer to struct adjlistnode.
I think it is a pointer to a list of pointers to adjlistnode structures
No, it isn't.
AdjMatrix becomes a type representing a pointer to pointer to struct adjlistnode
As an example it can be used like:
AdjMatrix p = NULL; // p is now a pointer to pointer to struct adjlistnode
The code seems to be for building a linked list and AdjMatrix seems to be a short hand for referring to a pointer to the head pointer. It could be used like:
void addNode(AdjMatrix pHead, int node, int cost)
{
struct adjlistnode *tmp = malloc(sizeof *tmp);
tmp->node = node;
tmp->cost = cost;
tmp->next = *pHead;
*pHead = tmp;
}
void deleteNode(AdjMatrix pHead)
{
if (*pHead)
{
struct adjlistnode *tmp = *pHead;
*pHead = tmp->next;
free(tmp);
}
}
int main(void) {
struct adjlistnode *head = NULL;
// Add nodes
addNode(&head, 1, 2);
addNode(&head, 3, 4);
addNode(&head, 5, 6);
// ... use the list
// Delete nodes
while(head) deleteNode(&head);
return 0;
}
Notice that typedef of pointers is often considered bad practice. Instead it would be better to do:
typedef struct adjlistnode {int node; int cost; struct adjlistnode *next;} AdjMatrix;
and use it like:
void addNode(AdjMatrix **pHead, int node, int cost)
to make it clear the pHead is a pointer to pointer to AdjMatrix
From typedef [emphasis added]:
typedef is a reserved keyword in the C and C++ programming languages. It is used to create an alias name for another data type. 1 As such, it is often used to simplify the syntax of declaring complex data structures consisting of struct and union types, but is just as common in providing specific descriptive type names for integer data types of varying lengths.
The AdjMatrix is an alternative name of struct adjlistnode ** type, which is a pointer to pointer to struct adjlistnode.
You can use it to declare variables like this:
AdjMatrix pp_st_adjlistnode;
which means pp_st_adjlistnode is a pointer to pointer to struct adjlistnode.

I'm getting the error: petition of a member in something that it's not an structure or an enum in C

Basically what I'm trying to do is to make a generic list in which I could put any data type inside the node by using a void* to it. This is the generic list and the structure I want to put inside of it.
typedef struct LIST{
struct LIST *next;
void *data;
} LIST;
struct person {
char *name;
int age;
};
This is the function to assign the pointer
LIST *create_node(void *data, int size) {
LIST *tmp;
tmp = NULL;
tmp = (LIST*)malloc(sizeof(LIST));
tmp->data = malloc(size);
tmp->data = data;
memcpy(tmp->data, data, sizeof(data));
tmp->next = NULL;
return tmp;
}
This is the function where I call the create_node function
void test_list() {
LIST *my_list;
struct person *my_person;
my_list = NULL;
my_person = (struct person*)malloc(sizeof(struct person));
strcpy(my_person->name, "PABLO");
my_person->age = 23;
my_list = create_node(my_person, sizeof(struct person));
printf("%d \n", my_list->data->age);
}
The problem comes in the last line in which I get the error: "petition of the member age in something that is not an structure or an enum". How can I get rid of this problem?
You've declared data as a void *. If you know for sure that it's really pointing at a person, then you'll need to cast:
((struct person *)my_list->data)->age
There are a couple of things I would do slightly differently, but the specific error here is in this expression:
my_list->data->age
remember from your declaration of the LIST type that the type of my_list->data is void *. You know that this particular void * actually points to a struct person -- but the compiler does not, and cannot know this, since these two functions might be in different files compiled at different times.
So, you need to explicitly tell the compiler that this void * should be treated as a struct person * using a type cast:
((struct person *)my_list->data)->age

Pointer to a Structure pointer

I have a structure as shown. And I am able to initialise or modify any of its members normally when I have a pointer to the structure.
struct node{
int key;
int nno;
char color;
struct node* out;
struct node* next;
struct node* pre;
};
But, When I pass an address of the structure pointer to a function and capture the same using a double pointer, and trying to access the members using that double pointer, my compiler is throwing an error 'member undefined'.
void DFSVisit(struct node** u){
*u->color = 'g';
struct node* v;
while(*u->out != NULL){
v = *u->out;
if(v->color == 'w'){
v->pre = *u;
DFSVisit(&v);
}
}
*u->color = 'b';
}
And, this is how I accessed the function.
DFSVisit(&root);
Root is a pointer properly initialized. And also, Root is a global variable.
Are you aware that the indirection (dereferencing) operator, *, has lesser precedence than the element selection operator, ->? That is, you should be writing (*u)->color, not *u->color.
*u->color parses as *(u->color) rather than your desired (*u)->color so the compiler complains because a node* has no color member (because it's a pointer rather than a struct!). So either explicitly insert the brackets like (*u)->color or introduce a local variable: struct node *node = *u; and use node->color

what does typedef struct node *NODE indicate?

struct node
{
int coef;
int exp;
struct node *link;
};
typedef struct node *NODE;
It defines NODE as a synonym for the type struct node *, so when you'll be declaring a variable of type NODE you'll be actually declaring a pointer to struct node.
Personally, I don't think that such declaration is a good idea: you're "hiding a pointer" (which is almost always a bad idea), and, moreover, you are not highlighting this fact in any way into the new name.
It makes NODE a typedef for a struct node *.
NODE becomes an alias for struct node*.
EDIT: Okay, for the comment (if I write my answer as comment, it would be too long and not formatted):
There's no different way to write this. Here, typedef is used just to create a synonym/alias for pointer to struct node.
An example for usage would be:
void f()
{
// some code
NODE p = NULL;
// do something with p
// for example use malloc and so on
// like: p = malloc( sizeof( struct node ) );
// and access like: p->coef = ..; p->expr = ..
// do something with p and free the memory later (if malloc is used)
}
is the same as
void f()
{
// some code
struct node* p = NULL;
// do something with p
}
Using NODE makes it just shorter (anyway, I wouldn't advise such typedef, as you're hiding, that it's a pointer, not a struct or other type, as mentioned in #Matteo Italia's answer).
The format, you're referring: "typedef struct{}type_name format" is something else. It's kind of a trick in C, to avoid writing struct keyword (as it's obligatory in C, and NOT in C++). So
typedef struct node
{
//..
} NODE;
would make NODE alias for struct node. So, the same example as above:
void f()
{
// some code
NODE p;
// do something with p
// note that now p is automatically allocated, it's real struct
// not a pointer. So you can access its members like:
// p.coef or p.expr, etc.
}
is the same as
void f()
{
// some code
struct node p;
// do something with p
}
NOTE that now, p is NOT a pointer, it's struct node.
simply tells you can create pointer of node type using only NODE every time instead of writting struct node * everytime
what does typedef struct node *NODE indicate?
UPPERCASE IS NO GOOD
Reserve ALL UPPERCASE identifiers for MACROS.

Need some help with Linked Lists;

I have a simple question in understanding the pointers and struct definitions in the linked list code.
1)
typedef struct node
{
struct node* next;
int val;
}node;
here if I use two "node" when i initialize node *head; which node I am referring to?
2) Here I use an int val in the struct. If I use a void* instead of int is there any thing thats going to change ?
3)Also if I pass to a function
reverse(node* head)
{
node* temp = head; or node* temp = *head;
//what is the difference between the two
}
I am sorry if these are silly question I am new to c language.
Thanks & Regards,
Brett
<1>
in C you need to specify struct node for structs
struct node
{
...
} node;
the last 'node' is variable of type struct node
e.g.
node.val = 1;
and not a type.
if you want to use 'node' as a type you need to write
typedef struct node { .. } node;
<2>
if you use void* you will need a mechanism to handle what the pointers point to e.g. if void* points to an integer you need keep the integer either on the stack or the heap.
node n;
int value = 1;
n.val = &value; // pointing to a single integer on stack
int values[]={1,2,3};
n.val = values; // pointing to an array of integers on stack
void* ptr = malloc(sizeof(int));
n.val = ptr; // pointing to a single (uninit) integer allocated on heap
int* ptrval = (int*)ptr; // setting an int ptr to the same memory loc.
*ptrval = value; // ptrval now points to same as n.val does
<3>
reverse(node* head)
head is a pointer to your list, *head is the content of what the pointer points to (first node below)
head->[node next]->[node next]->[node
next]
EDIT: rephrased and edited.
EDITx2: apparently the question got edited and a typedef was added so the question was altered.
*head is the dereference of the pointer : ie the actual place in memory that is pointed to by the pointer head...
Think of head as a coat hanger and *head as the coat itself, if that helps.
ie:
struct * coat c; //this is a coat hanger, not a coat
....
struct coat k = *c;//this is the coat itself, not a coat hanger
For #1:
In C, struct's have a separate name space. So if you wrote:
struct foo { ... };
You then have to use struct foo to reference the type. If you tried just foo after the above definition, the compiler would give an error as it doesn't know anything about that unqualified name.
A typedef gives a type an alternate name. A typedef name does not need to be qualified, so once you do:
typedef struct foo foo;
You can now use an unqualified foo to reference the type. Since it's just an alternate name, you can now use struct foo and foo interchangeably.
For #2.
It's possible that if you changed val to a void * it could change the size of the entire structure. Whether that makes a difference will depend on how you've written the rest of your code.

Resources