Ansi C linked List what am i doing wrong? - c

It crys that line:
List_Node * node = (List_Node*) malloc(sizeof(List_Node));
fails on :
1>list.c(31): error C2275: 'List_Node' : illegal use of this type as an expression
1>list.c(8) : see declaration of 'List_Node'
H FILE :
#ifndef _LIST_H
#define _LIST_H
typedef struct List_Node;
typedef struct List_Struct
{
unsigned int count;
struct List_Node * root;
struct List_Node * last;
int SizeOfData;
}List_Struct;
#endif
C_FILE :
typedef struct List_Node
{
void * data;
struct List_Node * next;
}List_Node;
Status List__Add (List_Struct * This,void * const item)
{
Assert(This)
Assert(item)
struct List_Node * node = (List_Node*) malloc(sizeof(List_Node));
IsAllocated(node);
node->data = malloc(This->SizeOfData);
IsAllocated(node->data);
memcpy(node->data,item,This->SizeOfData);
node->next = NULL;
if(NULL == This->root) /*if first item to be added*/
{
This->root= node;
This->last =This->root;
}
else
{
This->last->next = node;
}
return STATUS_OK;
}

The VC compilers only support the C89 standard so variables must be declared at the beginning of a scope, before any other statements.
Change List_Add() to:
Status List__Add (List_Struct * This,void * const item)
{
List_Node* node;
Assert(This)
Assert(item)
/* Don't cast return type of malloc(): #include <stdlib.h> */
node = malloc(sizeof(List_Node));
IsAllocated(node);
...
}

You defined list node as
typedef struct List_Node
then you say struct *List_Node.
The struct is unneccessary.

Related

struct that holds struct, how to dereference

i have couple of linked lists in my larger program which i now want to keep in a struct (t_holder).
typedef struct s_list
{
int val;
struct t_list *next;
} t_list;
typedef struct s_holder
{
t_list *a_starts;
// more lists...
} t_holder;
now i try to figure out how i dereference this in my program.
void try_out(t_holder *list_holder, int num)
{
//assigning something to a_starts
list_holder->a_starts->val = num;
}
int main(int argc, char *argv[])
{
t_holder *list_holder;
int num;
num = 42;
list_holder = NULL;
try_out(list_holder, num);
return (0);
}
in the function "try_out" i simlpy try to assign a value to a_starts->val but my debugger shows me ACCESS_ERROR if i declare it like this
list_holder->a_starts->val = num;
For starters this typedef declarations
typedef struct s_list
{
int val;
struct t_list *next; // <===
} t_list;
is incorrect. It seems you mean
typedef struct s_list
{
int val;
struct s_list *next; // <===
} t_list;
As for your other code then you declared a null pointer
t_holder *list_holder;
//...
list_holder = NULL;
So dereferencing the null pointer results in undefined behavior.
You need to write something like the following
t_holder list_holder = { .a_starts = NULL };
//...
try_out( &list_holder, num);
and then within the function something like
void try_out(t_holder *list_holder, int num)
{
t_list *node = malloc( sizeof( *node ) );
node->val = num;
node->next = list_holder->a_starts;
list_holder->a_starts = node;
}

C dereferencing pointer to incomplete type struct

In the tree.h header, I declared "struct privates" in order to hide the global variables. (relevant snippet)
struct privates;
/*
* a tree
*/
typedef struct tree_node
{
struct tree *left;
struct tree *right;
struct tree_node *left;
struct tree_node *right;
float * info;
float distance_to_neighbor;
} tree_node;
typedef struct tree
{
/*in order to keep track of the kd-tree root*/
tree_node * _root;
/*pointer to internal variables struct*/
struct privates* _privates;
} tree;
struct privates* init_heap_tree();
etc....
In the implementation file kdtree.c , I defined the "struct privates": (relevant snippet)
tree* my_tree=NULL;
typedef struct privates
{
/*variables*/
int current_number_of_tree_nodes;
/*previous tree rebuild's node count*/
int previous_tree_size;
} privates;
privates* init_heap_tree()
{
return (privates*) calloc(1, sizeof (privates));
}
tree* tree_get_tree()
{
my_tree = get_pre_allocated_tree();
return my_tree;
}
etc...
Now in the memory management code, see relevant snippet of init_heap().
I’m attempting to set initialize values for struct members "tree_space->_privates->current_number_of_tree_nodes = 0;"
void
init_heap (int max_dimensions)
{
tree_space = (tree *) calloc (tree_HEAP_SIZE, sizeof (tree));
tree_space = get_pre_allocated_tree();
tree_space->_privates = init_heap_tree();
//THIS IS WERE COMPILE TIME ERROR OCCURS
tree_space->_privates->current_number_of_tree_nodes = 0;
tree_space->_privates->previous_tree_size =0;
//allocate memory based on tree_HEAP_SIZE
tree_space = (tree_node*) calloc (tree_HEAP_SIZE, sizeof (tree_node));
tree_set_k_dimensions (max_dimensions);
etc...
}
"error: dereferencing pointer to incomplete type "struct privates"
I don't want any other design pattern for information hiding perse, How can I resolve this error with the struct member access?
Thanks a million.
Only functions in kdtree.c can access the members of private, so you need to do the initialization there.
privates* init_heap_tree()
{
privates *rval = calloc(1, sizeof (privates));
rval->current_number_of_tree_nodes = 0;
rval->previous_tree_size = 0;
return rval;
}

Undeclared identifiers with structs

struct FailedTransaction{
OrderNodePtr order;
int failureID;
struct FailedTransaction* next;
struct FailedTransaction* tail;
};
typedef struct FailedTransaction* FailedTransactionPtr;
struct SuccessfulTransaction{
OrderNodePtr order;
struct SuccessfulTransaction* next;
struct SuccessfulTransaction* tail;
};
typedef struct SuccessfulTransaction* SuccessfulTransactionPtr;
struct FinalReport{
FailedTransactionPtr failedTransactions;
SuccessfulTransactionPtr successfulTransactions;
};
struct FinalReport* report = NULL;
This code is declared above main. When accessing
report->successfulTransactions
or
report->failedTransactions
I get undefclared identifier for FailedTransaction and SuccessfulTransaction.
Here is the code that manipulates report
if(report == NULL){
report = malloc(sizeof(struct FinalReport));
report->failedTransactions = NULL;
report->successfulTransactions = NULL;
}
if(outcome){
if(report->successfulTransactions == NULL){
report->successfulTransactions = malloc(sizeof(SuccessfulTransaction));
report->successfulTransactions->order = temp;
report->successfulTransactions->tail = report->successfulTransactions;
}else{
report->successfulTransactions->tail->next = malloc(sizeof(SuccessfulTransaction));
report->successfulTransactions->tail->next->order = temp;
report->successfulTransactions->tail = report->successfulTransactions->tail->next;
}
}else{
if(report->failedTransactions == NULL){
report->failedTransactions = malloc(sizeof(FailedTransaction));
report->failedTransactions->order = temp;
report->failedTransactions->tail = report->failedTransactions;
}else{
report->failedTransactions->tail->next = malloc(sizeof(FailedTransaction));
report->failedTransactions->tail->next->order = temp;
report->failedTransactions->tail = report->failedTransactions->tail->next;
}
report->failedTransactions->failureID = outcome;
}
The errors occur at the first lines after each if statements and else statements.
This is for an assignment and I have been stuck on this for an hour or so (it is due tomorrow night). Can't figure out why it is happening and I can't find anything online. Any help would be appreciated.
This is the header file that contains OrderNodePtr
#ifndef _CONSUMER_
#define _CONSUMER_
struct OrderNode{
char title[250];
int id;
double cost;
char category[250];
struct OrderNode* next;
struct OrderNode* tail;
};
typedef struct OrderNode* OrderNodePtr;
#endif
Try
sizeof(struct FailedTransaction);
Or, make FailedTransaction a typedef:
struct _FailedTransaction;
typedef struct _FailedTransaction FailedTransaction;
struct _FailedTransaction {
OrderNodePtr order;
int failureID;
FailedTransaction* next;
FailedTransaction* tail;
};
Why does C need "struct" keyword and not C++?

Why my double linked list insertion fail?

I am writting a simple timer with a double linked list.If I define the linked list head as below,It will work.
struct timer_head
{
struct timer* prev;
struct timer* next;
pthread_spinlock_t lock;
};
But if I define the head as below, then the insertion will fail,I will lost the previous node after each insertion.
struct timer_head
{
struct timer* next;
struct timer* prev;
pthread_spinlock_t lock;
};
Part of my code:
struct timer
{
struct timer* prev;
struct timer* next;
struct timespec start;
struct timespec interval;
void* par, *par2;
/*if handle return 0 */
/*then delete this timer */
/*else restart it */
int (*handler) (void* par);
};
struct timer_head
{
struct timer* prev;
struct timer* next;
/*
*if i changed the previous definition to
*code below, then my list insertion will failed
*why?
*/
/* struct timer* next;
struct timer* prev;
*/
pthread_spinlock_t lock;
};
void timer_queue_init(struct timer_head* lst)
{
pthread_spin_init(&lst->lock, PTHREAD_PROCESS_SHARED);
lst->next = lst->prev = (struct timer*)lst;
}
static void print_queue(struct timer_head* lst)
{
pthread_spin_lock(&(lst->lock));
struct timer* fst = lst->next;
printf("list travserse:\t");
while (fst != (struct timer*) lst)
{
printf("inteval : %ld, ", fst->interval.tv_nsec);
fst = fst->next;
}
printf("\n");
pthread_spin_unlock(&(lst->lock));
}
void timer_queue_insert(struct timer_head* lst, struct timer* nt)
{
pthread_spin_lock(&(lst->lock));
struct timer* ptr = lst->next;
/*insert into list, sorted as earlist execute time */
while (ptr != (struct timer*) lst &&
timespec_cmp(&(ptr->start), &(ptr->interval),
&(nt->start), &(nt->interval)) <= 0)
{
printf("next\n");
ptr = ptr->next;
}
nt->next = ptr;
nt->prev = ptr->prev;
nt->prev->next = nt;
ptr->prev = nt;
/* send signal to manage thread */
if (!qlen)
{
printf("start :%ld s, %ld ns ", nt->start.tv_sec, nt->start.tv_nsec);
printf("interval :%lds, %ld ns\n", nt->interval.tv_sec, nt->interval.tv_nsec);
pthread_cond_signal(&wait);
}
++qlen;
pthread_spin_unlock(&(lst->lock));
printf("traver after insert\t");
print_queue(lst);
}
This code casts a pointer to a struct timer_head to a pointer to a struct timer.
void timer_queue_init(struct timer_head* lst)
{
pthread_spin_init(&lst->lock, PTHREAD_PROCESS_SHARED);
lst->next = lst->prev = (struct timer*)lst; /* HERE */
}
This works (by luck) so long as they have the same structure. Your struct timer looks like this:
struct timer
{
struct timer* prev;
struct timer* next;
...
So putting prev before next allows the cast to "happen to" preserve the values of prev and next, though you definitely shouldn't do it. The problem with code that "happens to" work is that sometimes it will happen not to work.
Looking at your code, the problem is that you cast a timer_head * to timer *. If timer_head looks like
struct {
struct timer * next;
struct timer * prev;
...
}
then in memory you (may) have the following layout
[next][prev]
. If at the same time timer looks like
struct {
struct timer * prev;
struct timer * next;
...
}
, as in your code, it has a different layout in memory, i.e. something like
[prev][next]
. Your cast from one pointer to the other changes what prev and next stand for. (In one case the first and second pointer in memory, in the other case the second and first pointer in memory).

C Error: dereferencing pointer to incomplete type

So im getting a "Line 51: error: dereferencing pointer to incomplete type" when running this:
int main(void)
{
Tree * testTree;
testADT * data1;
testTree = createTree(compare,destroy);
data1 = malloc(sizeof(testADT));
data1->val = 10;
/* Line 51 */ addToTree(testTree,testTree->root,data1);
destroyBinTree(testTree);
return(0);
}
my addToTreeFunction:
TreeNode * addToTree(Tree * theTree,TreeNode * theTreeNode, TreeDataTypePtr data)
{
TreeNode * newNode;
if(isEmpty(theTree))
{
newNode = malloc(sizeof(TreeNode));
newNode->height = 0;
newNode->data = data;
theTree->root = newNode;
return theTree->root;
}else{
if(theTree->compare(theTreeNode->data,data) == 1) /* shows root data is smaller */
{
theTreeNode->right = addToTree(theTree,theTreeNode->right,data);
}else
if(theTree->compare(theTreeNode->data,data) == 0) /* shows root data is larger */
{
theTreeNode->left = addToTree(theTree,theTreeNode->left,data);
}
}
return theTreeNode;
}
my typedefs and structs:
struct tADT{
int val;
};
typedef struct tADT testADT;
typedef void * TreeDataTypePtr;
Could anyone provide some insight into whats going on? Thanks-in advance!
Edit: This is in my module (.c)
struct AvlNode{
void * data;
struct AvlNode * left;
struct AvlNode * right;
int height;
};
struct AvlTree{
int (*compare) (TreeDataTypePtr data1, TreeDataTypePtr data2);
void (*destroy) (TreeDataTypePtr data);
struct AvlNode * root;
};
this is in the header (.h)
struct AvlTreeNode;
struct AvlTree;
typedef struct AvlTree Tree;
typedef struct AvlNode TreeNode;
typedef void * TreeDataTypePtr;
Problem fixed by defining all structs/typedefs in header:
typedef struct AvlTree Tree;
typedef struct AvlNode TreeNode;
typedef void * TreeDataTypePtr;
struct AvlNode{
void * data;
struct AvlNode * left;
struct AvlNode * right;
int height;
};
struct AvlTree{
int (*compare) (TreeDataTypePtr data1, TreeDataTypePtr data2);
void (*destroy) (TreeDataTypePtr data);
struct AvlNode * root;
};
Are you defining "Tree" somewhere in one of your header files? Can line 51 of the failing module see that header?
You must define "Tree" :)
===================== ADDENDUM ====================
Thank you for updating your post with your "definition" of Tree:
// .h file
struct AvlTreeNode;
struct AvlTree;
typedef struct AvlTree Tree;
...
But the fact remains - these are both "incomplete types".
You say you defined AvlTree and AvlTreeNode "in your module (.c)".
Q: Which .c translation unit?
Q: Is it defined in that translation unit before you try to use it?
Q: Is it used in any other translation unit?
Q: Why the duplicate/redundant/confusing typedef aliases?
Q: Why, for heaven's sake, don't you just define it in your .h file?
testTree->root dereferences testTree, which is of type Tree, which isn't defined anywhere.
The error suggests that you have a forward declaration of Tree, but not a full definition of its corresponding structure. That is why you can declare a pointer to Tree, but you are not allowed to dereference its members.
Make sure that the compilation unit that contains main has a #include at the top for the header file that contains the definition of struct Tree, this will fix this problem.

Resources