Dereferencing pointer to incomplete type - c

I am new to C programming and as a mini project I decided to try to implement a stack in C using OOP style structure in a file GenericStack.h as shown below:
void _GENERICSTACK0001(void *,void *);
void *_GENERICSTACK0002(void *);
int _GENERICSTACK0003(void *);
typedef struct
{
struct GenericStackNode *next;
void *data;
int type;
}GenericStackNode;
typedef struct
{
struct GenericStackNode *top;
int count;
void (*add)(void *,void *);
void *(*pop)(void *);
int (*hasNext)(void *);
int (*getCount)(void *);
}GenericStack;
GenericStack newGenericStack()
{
GenericStack *genStack = malloc(sizeof(GenericStack));
genStack->add = _GENERICSTACK0001;
genStack->pop = _GENERICSTACK0002;
genStack->hasNext = _GENERICSTACK0003;
genStack->getCount = _GENERICSTACK0003;
genStack->top=NULL;
genStack->count = 0;
return *genStack;
}
void _GENERICSTACK0001(void *self,void *data)//add
{
GenericStack *genStack = self;
if(genStack->top == NULL)
{
genStack->top = malloc(sizeof(GenericStackNode));
genStack->top->next = NULL;
genStack->top->type = 0;
genStack->top->data = data;
}
else
{
GenericStackNode *temp = malloc(sizeof(GenericStackNode));
temp->next = genStack->top;
temp->type = 0;
temp->data = data;
genStack->top = temp;
genStack->count++;
}
}
void *_GENERICSTACK0002(void *self)//pop
{
GenericStack *genStack = self;
void *data = NULL;
if(genStack->top == NULL)
{
return data;
}
else
{
GenericStackNode *temp = genStack->top;
genStack->top = genStack->top->next;
data = temp->data;
free(temp);
genStack->count--;
return data;
}
}
int _GENERICSTACK0003(void *self)
{
GenericStack *genStack = self;
return genStack->count;
}
All I need to know is why (among many others) I get the specific error:
GenericStack.h:41:16: error: dereferencing pointer to incomplete type
genStack->top->type = 0;
I have checked the other answers on stackoverflow concerning "dereferencing pointer to incomplete type" but I cant seem to understand.

You're getting an error from GenericStack, but you have a problem in both GenericStack and GenericStackNode.
In C, struct X and X are different types. When you write:
struct GenericStackNode *next;
it declares a type called struct GenericStackNode (and a member which is a pointer to that type). This type is incomplete because you have not provided the struct definition.
The type could be completed by providing a struct definition later, but you never do that. Instead, you define an unnamed struct and typedef GenericStackNode to it , but that has no effect on struct GenericStackNode.
Then, struct GenericStackNode *top; still uses this same incomplete type, not the struct you defined above.
Assuming you meant for this pointer to be a pointer to the same type of struct it's contained in, you could use this pattern for both of your structs:
typedef struct X X;
struct X
{
X *ptr;
};
Often people combine the typedef with the struct definition but I find it clearer to have them separate.

You already type-defined GenericStackNode as a type, there is no need for struct GenericStackNode anymore, just GenericStackNode :
typedef struct
{
struct GenericStackNode *top;
...
}
should be only
typedef struct
{
GenericStackNode *top;
...
}
also , you can't use GenericStackNode when you still havn't defined it yet :
typedef struct
{
struct GenericStackNode *next;
void *data;
int type;
} GenericStackNode ;
you can write :
typedef struct GenericStackNode
{
struct GenericStackNode *next;
void *data;
int type;
} GenericStackNode ;

Related

Void * that saves different structs

typedef struct s_list
{
void *content;
struct s_list *next;
} t_list;
typedef struct s_env
{
char *key;
char *val;
struct s_env *next;
} t_env;
typedef struct s_heredoc
{
char *term;
char *delimiter;
char *heredoc;
} t_heredoc;
typedef struct s_cmd
{
char *cmd;
char *path;
int istream;
int ostream;
} t_cmd;
typedef struct s_table{
char **paths;
char **reserved;
char *cmdline;
t_list *cmds;
} t_table;
I have a general struct t_table which have a pointer to t_list struct called cmds.
How can i save different structs for example t_env, t_heredoc, t_cmd in void * content; property of t_list struct. How should I cast the void * content to another type (t_env, t_cmd, t_heredoc, etc)
void lexical_analyze(char *cmdline, t_table **table)
{
cmdline = openquotes(cmdline);
cmdline = find_replace(cmdline, (*table)->env);
(*table)->cmds = malloc(sizeof(t_list));
}
After this point i can’t understand how to cast and how to allocate a memory for the other structs for example t_cmd struct
You can assign a pointer to any struct to your context member. But if you want to use that struct later, you will need to recover the original pointer type. That means you must store extra information about type of your content in your struct:
typedef enum {
CT_Env,
CT_Cmd,
CT_HereDoc
} t_context_type;
typedef struct s_list
{
void *content;
t_context_type type;
struct s_list *next;
} t_list;
t_list *add_Env(t_env *env)
{
t_list *list = malloc(sizeof *list);
... Do the list handling...
list->context = env;
list->type = CT_Env;
return list;
}
Then, when you want to access the nodes of your list you can cast to correct type:
void handle_node(t_list *list)
{
switch (list->type)
{
case CT_Env:
{
t_env *env = list->context;
// Access members of t_enf via env pointer
}
break;
case CT_Cmd: // TODO handle t_cmd type
break;
case CT_HereDoc: // TODO handle t_heredoc type
break;
default: // TODO: Error handling
break;
}
}
Of course that code is not complete. It should show how it is supposed to work.

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;
}

Initialize a struct in C using {}

In the marked line I get an error Error - expected expression
#include <stdlib.h>
struct list_head {
struct list_head *next, *prev;
};
struct program_struct {
const char *name;
struct list_head node;
};
typedef struct program_struct program_t;
struct task_t {
program_t blocked_list;
};
int main() {
struct task_t *p = malloc(sizeof(*p));
p->blocked_list.name = NULL;
p->blocked_list.node = {&(p->blocked_list.node), &(p->blocked_list.node)}; //error
return 0;
}
I know I can replace this line with
p->blocked_list.node.next = &(p->blocked_list.node);
p->blocked_list.node.prev = &(p->blocked_list.node);
But can I make it work using {} like I tried in the first piece of code?
Initialization is allowed only when you define a variable. So, you can't use initializers in assignment.
You can instead use C99's compound literals:
p->blocked_list.node = (struct list_head) {&(p->blocked_list.node), &(p->blocked_list.node)}; //error

deferencing pointer to incomplete type on my custom list

I'm writing a custom list with some operations on it but i'm having trouble with the "deferencing pointer to incomplete type error"
here are the struct definitions:
typedef struct TIME_NODE {
int timeout;
int seq_number;
struct time_node* next;
} time_node;
typedef struct TIMEOUT_LIST {
struct time_node* head;
} timeout_list;
And here is one of the functions
void insert(timeout_list *l, int sequence_number, int timeout)
{
int c=0;
struct time_node* temp;
temp = l->head;
if(temp==NULL)
{
add(sequence_number, timeout);
}
else
{
while(temp!=NULL)
{
if(temp->timeout < timeout) {
c++;
}
temp = temp->next;
}
if(c==0)
add(sequence_number, timeout);
else if(c<count())
add_after(sequence_number, timeout, ++c);
else
append(sequence_number, timeout);
}
}
Why can't I deference temp?
This is wrong
struct time_node* temp;
it should be
struct TIME_NODE* temp;
but since you have typedefed it, then this should be enough
time_node* temp;
and you should fix it in the struct TIMEOUT_LIST too.
If you want either syntaxes to work then you have to use the same name for the struct and for the typedef like this
typedef struct time_node {
int timeout;
int seq_number;
struct time_node* next;
} time_node;
and you can even do it this way
typedef struct time_node time_node;
struct time_node {
int timeout;
int seq_number;
time_node* next;
};
typedef struct TIME_NODE {
int timeout;
int seq_number;
struct time_node* next;
} time_node;
That will create a struct type called TIME_NODE (which can be declared using struct TIME_NODE, and then typedefs it to time_node.
You either need to declare the variable using the type struct TIME_NODE*, or time_node*.

Resources