I have this code:
typedef struct node
{
char* data;
struct node next;
} node;
typedef struct linkedList
{
node head;
int size;
} linkedList;
typedef struct _MyLinkedList *MyLinkedListP
{
struct linkedList* listp;
};
MyLinkedListP createList()
{
linkedList *list = (linkedList*)malloc(sizeof(linkedList));
(*list).head = NULL;
(*list).size = 0;
MyLinkedListP listP = list;
return listP;
}
I am trying to build a function:
MyLinkedListP cloneList(MyLinkedListP l)
l is a pointer to a linkedList, I am trying to get its members (size and first node), in order to complete the function. But I just do not understand how to do it under this build.
I also want to ask regarding my build of struct MyLinkedListP. My goal was to create a type that is a pointer to a linkedList, is the way I did it good practice?
First of all, this won't work:
typedef struct node
{
char* data;
struct node next;
} node;
A struct type may not contain a member that's an instance of itself1; this should be written as
typedef struct node
{
char* data;
struct node *next; // next is a *pointer* to struct node
} node;
Secondly, while the following isn't a problem like the above, this is not good practice:
typedef struct _MyLinkedList *MyLinkedListP
Identifiers with leading underscores are reserved for the implementation; you should not create any type or object names with leading underscores. Just use
typedef struct MyLinkedList *MyLinkedListP
instead2.
Third, lose the cast in
linkedList *list = (linkedList*)malloc(sizeof(linkedList));
It's not necessary (since C89), it clutters up the call, and it creates maintenance headaches. That can be made much simpler as follows:
linkedList *list = malloc( sizeof *list );
Fourth, note that you can write
(*list).head = NULL;
(*list).size = 0;
as
list->head = NULL;
list->size = 0;
a->b is shorthand for (*a).b, and makes things a little easier to read.
Finally,
MyLinkedListP listP = list;
is attempting to assing a value of type struct linkedList * to an object of type struct MyLinkedList *, and they aren't compatible. Based on the code you've shared, it looks like you meant to do something more like
struct MyLinkedList myList;
list.listp = list;
or
struct MyLinkedList myList = {list};
or even
MyLinkedListP listP = malloc( sizeof *listP ); // leaky abstraction from hiding
// pointer behind typedef
listP->listp = list;
I suggest you take a step back and try to simplify what you're doing - you've added a bit of unnecessary complexity with your types.
First of all, the struct node type isn't complete until the closing } of the struct definition, and you can't declare an instance of an incomplete type; you can, however, declare a pointer to an incomplete type. Secondly, the size to store an instance of struct node would have to be infinite, since the instance contains an instance of itself, which contains an instance of itself, which contains an instance of itself, etc.
A quick rant - as a rule, you should not hide pointers behind typedefs. If the programmer has to ever be aware that they are dealing with a pointer (for example, if they need to access members of the struct type), then make that explicit in the declaration of the pointer object (look at the FILE type in stdio.h as an example - even though you only ever deal with pointers to FILEs, that pointer is not part of the FILE typedef).
The definition of struct node won't compile, because it is trying to contain itself in its definition. Instead, use indirection via a pointer.
typedef struct node
{
char* data;
struct node *next;
} node;
The definition of struct _MyLinkedList is incorrect, since the body has to follow the tag. Mirror your syntax for struct node and place the alias after the struct declaration.
typedef struct _MyLinkedList
{
struct linkedList* listp;
} *MyLinkedListP;
Since the head member of struct linkedList is not a pointer variable, the assignment will not compile. If you meant for the assignment to succeed, then change the definition of struct linkedList accordingly.
typedef struct linkedList
{
node *head;
int size;
} linkedList;
Your are assigning a struct linkedList * to a struct _MyLinkedList *, but they are not compatible. Since your function wants to return a struct _MyLinkedList *, you should properly allocate one to be returned.
MyLinkedListP listP = malloc(sizeof(*listP));
listP->listp = list;
return listP;
With all the changes together, and fixing up some stylistic issues:
typedef struct node
{
char* data;
struct node *next;
} node;
typedef struct linkedList
{
node *head;
int size;
} linkedList;
typedef struct _MyLinkedList
{
struct linkedList* listp;
} *MyLinkedListP;
MyLinkedListP createList()
{
linkedList *list = malloc(sizeof(*list));
list->head = NULL;
list->size = 0;
MyLinkedListP listP = malloc(sizeof(*listP));
listP->listp = list;
return listP;
}
Related
I created a doubly linked list and in the function that adds values to the list, it calls the function list_next which is supposed to return the next node in the list but I'm unable to figure out just how to do that. I feel like ListPos Pos is a double pointer hence why I wrote my code like that, but it's apparently wrong. How should I go about writing it and how would I avoid that mistake in the future?
struct node
{
struct node *next;
struct node *prev;
char *value;
};
typedef struct list_pos
{
struct node *node;
} ListPos;
ListPos list_next(ListPos pos)
{
return &(*pos.node)->next;
}
Here's your code with some changes, explained in comments, which hopefully will help you:
struct node
{
struct node *next;
struct node *prev;
char *value;
};
// typedefs are more confusing than they are useful
struct list_pos
{
struct node *node;
};
struct list_pos list_next(struct list_pos pos)
{
// don't be afraid to use temp variables to make your code clearer
struct node *current = pos.node;
assert(current != NULL); // one way to indicate assumption
// you could also check if current is NULL and return NULL in that case
struct node *next = current->next;
return (struct list_pos){next}; // compound literal to avoid temp variable
}
&(*pos.node)->next doesn't make any sense.
You probably want this:
ListPos list_next(ListPos pos)
{
ListPos next;
next.node = pos.node->next;
return next;
}
What Jabberwocky suggested is the right answer. I just wanted to add that you could replace
typedef struct list_pos
{
struct node *node;
} ListPos;
with
typedef struct node* ListPos;
because you looked like you were thinking that ListPos is a pointer rather than separate struct.
typedef struct HashNode{
int data;
struct node *next;
}node;
node *addThisNode = malloc(sizeof(node));
addThisNode->data = scannedInt;
addThisNode->next = NULL;
node **hashTable = malloc(10000*sizeof(node));
for (int i =0 ; i < 10000; i ++){
hashTable[i] = NULL;
}
void append(node **hashTable, node *addThisNode, int hashedValue){
node *ptr = hashTable[hashedValue];
while (ptr->next != NULL){
ptr = ptr->next;
}
ptr->next = addThisNode;
}
The following is a hash table in C. I defined the table to be an array of pointers to nodes. In the case of a collision, I implemented node chaining via the append function. Now, when I go to increment the pointer in the append function, I am getting an "assignment from incompatible pointer type" error, and the same error when I try to assign ptr->next to the addThisNode. My understanding now is that by doing
"ptr->next = addThisNode" , they are the same type, Node, and should work.
What am I doing wrong?
What is wrong is that struct node and struct HashNode are different types.
The node typedef name is an alias for struct HashNode and has nothing to do with struct node.
typedef struct HashNode {
int data;
struct node *next; // this should be struct HashNode
} node;
I suggest using struct node instead of struct HashNode, or vice versa: use the same identifier for the struct tag and for the typedef name:
typedef struct HashNode {
int data;
struct HashNode *next; // this should be struct HashNode
} HashNode;
If struct HashNode and HashNode are the same via typedef, and no identifier other than HashNode is introduced, you are less likely to run into this sort of confusion.
struct xxx {
int data;
struct xxx *next;
};
typedef struct xxx node;
node **hashTable = malloc(10000*sizeof * hashTable);
for (int i =0 ; i < 10000; i ++){
hashTable[i] = NULL;
}
void append(node **hashTable, node *addThisNode, int hashedValue){
node **pp ;
for(pp = &hashTable[hashedValue]; *pp; pp = &(*pp)->next) {;}
*pp = addThisNode;
}
O, and BTW: you don't need the typedef. I only causes confusion.
typedef struct HashNode{
int data;
struct node *next;
}node;
In this construction, node is a type (but only after the typedef statement), and is equivalent to say struct HashNode. What is not a type is to say struct node, which is an incomplete structure type, and a pointer to it will generate the error you post in the question title if you try to dereference it (the compiler doesn't know, because you have not yet defined the internal structure of struct node type)
Of course, the types struct node and node have nothing in common (the first is a complete type, the second is an incomplete, not yet defined type) and this is the reason that a pointer to one is not compatible with a pointer to the other type.
You could have said:
typedef struct HashNode{
int data;
struct HashNode *next;
} node;
or
/* forward reference, struct HashNode is not yet complete,
* but the compiler knows already that node is a type. */
typedef struct HashNode node;
struct HashNode{
int data;
node *next;
}; /* now struct HashNode type is complete */
In this last second way, the incomplete definition is used to know that the type node is defined as some incomplete structure, in order to be able to use it later in the node *next; declaration. Had we not done it first, the node *next; definition would have given an error, as the type node had not yet been defined.
In C, the names used for struct, union, enumtypes belong to a different namespace than the named types themselves, sostruct foois not the same asfoo(this is not true in C++, where for eachstruct fooyou are creating aclasswith all memberspublic`, probably your mistake comes from using a c++ compiler)
A few days ago I made a function, which worked just fine. This is struct defining I used.
typedef struct {
int data;
struct Node * next;
} Node;
typedef struct {
Node * head;
Node * current;
int size;
} List;
Then I have this function
void returnMiddle(List * list){
Node * first = list->head;
Node * second = list->head;
if(list->head != NULL){
while(second != NULL && second->next != NULL){
first = first->next;
second = first->next->next;
}
printf("Middle is: %d", first->data);
}
}
But now I receive given error and I don't understand why? Does anyone know?
second = first->next->next; <<< this is where I get an error message, up to here it works fine
In this typedef declaration of a structure
typedef struct {
int data;
struct Node * next;
} Node;
the type struct Node is an incomplete type. That is the type name struct Node is introduced but not defined.
Pay attention that the typedef name Node and the type name struct Node name two different entities. The name Node names an unnamed structure while struct Node names a not yet defined structure.
It is obvious that you mean the following
typedef struct Node {
int data;
struct Node * next;
} Node;
error: dereferencing pointer to incomplete type
This means that the compiler couldn't find a definition of the struct within the translation unit where you made that access - it could only find a declaration. struct Node * next; is as it turns out, a pointer to a type that wasn't previously defined at the point where you declared it. Because it only becomes defined when the compiler reaches the }; of the struct.
For a self-referencing struct, you need to forward-declare the type in order to use it as a struct member. Depending on your coding style that either means:
typedef struct Node Node;
struct Node {
int data;
struct Node* next; // also possible: Node* next;
};
or
typedef struct Node {
int data;
struct Node* next;
} Node;
(The type Node and the struct tag Node actually live in separate namespaces, but this is one of those things one need not ponder about - just do.)
struct Node * next;
struct Node is a forward declaration to structure Node, but you havenĀ“t defined a structure called Node yet - means struct Node is an incomplete type.
typedef struct {
...
} Node;
Node is a typedef for the structure definition. it is not equal to struct Node.
Provide the structure tag Node:
typedef struct Node {
int data;
struct Node * next;
} Node;
and your code works fine.
Also have a look at here:
typedef struct vs struct definitions
This snippet of code is from an assignment I'm working on at school for a data structures module. This bit of code is provided in the question, and I can't understand this.
typedef struct _listnode {
int item;
struct _listnode *next;
} ListNode; // You should not change the definition of ListNode
typedef struct _linkedlist {
int size;
ListNode *head;
} LinkedList; // You should not change the definition of LinkedList
I am confused because my lecture slides and sites I've been to check this out have just defined the node, and not the second one.
Can anyone help me with this please?
LinkedList is a struct denoting a linked list by holding its head and its size, while each node in the list is denoted by struct ListNode. This is a common paradigm if you want to maintain the size of the linked list, in the case you can easily get the number of nodes in the list without have to iterate through it. On the other hand, if size is not concern, you can just use a pointer to node for the head without have to define the LinkedList struct.
So for an empty list, you would have:
LinkedList list = (struct LinkedList){0, NULL};
For a list with one node:
ListNode node;
node.item = 0;
node.next = NULL;
list.head = &node;
list.size = 1;
A linked list is held using a local pointer variable which points to the first item of the list. If that pointer is also NULL, then the list is considered to be empty.
include <stdio.h>
int main() {
typedef struct node {
int val;
struct node * next;
} node_t;
return 0;
}
I'm currently implementing a doubly-linked list in C. The purpose of the list is to be as generic as possible. Here's the node struct:
typedef struct list_node
{
struct list_node *prev;
struct list_node *next;
int nodeId;
} Node;
Now, I'm extending this into the following node:
typedef struct history_node
{
Node *node;
String *cmd;
} HistoryNode;
Where the string struct is defined as follows:
typedef struct c_string
{
char *array;
size_t size;
} String;
Now, the problem that I'm having is this: I create a new history node, and set it's string to a value, "hello" for example. I then call on my pushBack function, that is defined as follows:
void pushBack(Node *node, List *list)
{
node->next = list->tail;
node->prev = list->tail->prev;
list->tail->prev->next = node;
list->tail->prev = node;
list->size++;
}
The thing here is that when I assign node->next, instead of accessing the node part of the history node, I access the string, which results in disaster. I have no idea why this is happening. Looking at the addresses in memory, the pointer that is passed in has the correct address, but the address that is accessed in node->next corresponds to the address of cmd and not node. Any ideas?
Just in case, the code that calls this function is:
HistoryNode *node = createHistoryNode(buffer);
pushBack((Node*)node, historyList);
I have already verified that createHistoryNode works as expected, so that is not the source of the problem.
You don't want
typedef struct history_node {
Node *node;
String *cmd;
} HistoryNode;
you want
typedef struct history_node {
Node node;
String *cmd;
} HistoryNode;