Convert struct with dynamic arrays to double pointers - c

I had a data structure, which contain some dynamic sized fields.
I.e. void *methods[0] I also declared them as void *methods[], but this seems also wrong, because this shouldn't be the only field in the struct.
This structure is only to read memory which is defined somewhere else, so I can't just add the size of methods inside itable_t/itt_t and define methods/entries as dynamic.
The code below works, but give me some warnings which I don't want.
struct itable_t {
void *methods[0];
};
typedef struct itable_t itable_t;
struct itt_entry_t {
itable_t *itable;
void *id;
int32_t prev;
int32_t next;
};
typedef struct itt_entry_t itt_entry_t;
struct itt_t {
itt_entry_t entries[0];
};
typedef struct itt_t itt_t;
struct vtable_t {
rtti_t *rtti;
itt_t *itt;
void *dynamic_methods[];
};
typedef struct vtable_t vtable_t;
struct object_t {
vtable_t *vptr;
};
typedef struct object_t object_t;
So I tried to translate the structure to the following, which doesn't seems to be correct, because I get some segmentation faults
struct itt_entry_t {
void **itable;
void *id;
int32_t prev;
int32_t next;
};
typedef struct itt_entry_t itt_entry_t;
struct vtable_t {
rtti_t *rtti;
itt_entry_t **itt;
void *dynamic_methods[];
};
typedef struct vtable_t vtable_t;
struct object_t {
vtable_t *vptr;
};
typedef struct object_t object_t;
How should I define and access my structs, so that they work?
EDIT: How the structure is currently used:
The function is called from assembler
movl %edi, (%esp)
movl $itable_table_name_815, 4(%esp)
movl $0x4, 8(%esp)
call oo_searched_itable_method
c function
void *oo_searched_itable_method(const object_t *obj, void *interface_id, int32_t offset)
{
itt_t *itt = obj->vptr->itt;
int32_t i = 1;
do {
if (itt->entries[i].id == interface_id) {
return itt->entries[i].itable->methods[offset];
}
}
while (itt->entries[++i].id != NULL);
// should never happen
abort();
}

I solved the problem now with the following code - thanks for any help and good suggestions I got in the comments.
structure definition:
struct itt_entry_t {
void **itable;
void *id;
int32_t prev;
int32_t next;
};
typedef struct itt_entry_t itt_entry_t;
struct vtable_t {
rtti_t *rtti;
itt_entry_t *itt;
void *dynamic_methods[];
};
typedef struct vtable_t vtable_t;
struct object_t {
vtable_t *vptr;
};
typedef struct object_t object_t;
code which uses the structurs
void *oo_searched_itable_method(const object_t *obj, void *interface_id, int32_t offset) {
itt_entry_t *itt = obj->vptr->itt;
int32_t i = 1;
do {
if (itt[i].id == interface_id) {
return itt[i].itable[offset];
}
}
while (itt[++i].id != NULL);
fprintf(stderr, "ITable not found...");
abort();
}

According to me, i declare structures like that :
typedef struct s_data
{
char *str;
int foo;
} t_data;
Now in your code you need to declare it by this way :
t_data my_struct;
my_struct.foo = 8;
my_struct.str = malloc(4 * sizeof(char));
my_struct.str = strcpy(my_struct.str, "foobar");
But i need more informations from you, what are the warnings and show me how you declare and access your structure.

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.

Nested linked lists in C

I'm trying to implement a nested linked list in C, that will be used for a hierarchical menu. However, the GCC (v4.9.3-1) is complaining to nested structures, and I have no idea how to fix this. Here is the minimum (non)working example.
Is this nesting even possible in C?
main.c
#include "menu.h"
int main(void) {
Init_Menu();
return 0;
}
menu.c
#include "menu.h"
MenuItem_t LVL_0_MainMenu = {
.size = 0,
};
MenuItem_t LVL_1_Measurements = {
.size = 0,
};
void Init_Menu(void) {
Menu_Add_Child(&LVL_0_MainMenu, &LVL_1_Measurements);
}
void Menu_Add_Child(MenuItem_t *parent, MenuItem_t *child) {
parent->children[parent->size] = child;
child->parent = parent;
parent->size++;
}
menu.h
typedef struct {
unsigned char size;
MenuItem_t children[10];
MenuItem_t *parent;
} MenuItem_t;
extern MenuItem_t LVL_0_MainMenu;
extern MenuItem_t LVL_1_Measurements;
void Init_Menu(void);
void Menu_Add_Child(MenuItem_t *parent, MenuItem_t *child);
Based on answers by #bolov and #sps (once again, thanks to both of them), here is the minimum working example:
main.c
#include "menu.h"
int main(void) {
Init_Menu();
return 0;
}
menu.c
#include "menu.h"
MenuItem_t LVL_0_MainMenu = {
.size = 0,
};
MenuItem_t LVL_1_Measurements = {
.size = 0,
};
void Init_Menu(void) {
Menu_Add_Child(&LVL_0_MainMenu, &LVL_1_Measurements);
}
void Menu_Add_Child(MenuItem_t *parent, MenuItem_t *child) {
parent->children[parent->size] = child;
child->parent = parent;
parent->size++;
}
menu.h
struct MenuItem_t {
unsigned char size;
struct MenuItem_t *children[10];
struct MenuItem_t *parent;
};
typedef struct MenuItem_t MenuItem_t;
extern MenuItem_t LVL_0_MainMenu;
extern MenuItem_t LVL_1_Measurements;
void Init_Menu(void);
void Menu_Add_Child(MenuItem_t *parent, MenuItem_t *child);
The difference between this corrected program and the original (non)working program, is that the children array is defined as an array of pointers to variables of the type MenuItem_t instead of the array of variables of the same type. The other difference is that a nested list (inside the structure) should also contain the keyword struct as #bolov explained.
You need to use struct for the type used inside itself, even if you typedef it later on.
E.g. this won't work:
struct X_ {
X* next;
};
typedef struct X_ X;
But this will
struct X_ {
struct X_* next;
};
As a side note, I really don't like this form:
typedef struct {
} X;
I use:
struct X {
};
typedef struct X X;
But maybe this is just me being more fond of C++.
If you want to use that form, it's the same: you need to add struct and it works:
typedef struct {
struct X2* next;
} X2;
regarding:
struct X {
struct X arr[10];
};
You can't have that! The array is just in our way to understand why. So let's simplify:
struct X {
int a;
struct X var;
};
This can't be. What size would X be? sizeof(X) = sizeof(int) + sizeof(X) + padding. Do you see the problem? All you can do is have a pointer to X, but not an object X inside X.
Returning to your array. You need dynamic arrays:
struct X {
struct X* arr;
int arr_size;
};
It gets more complicated as you need to manage the memory (malloc/free fun), but you can't avoid it.
First of all, you cannot do,
typedef struct {
SomeName_t some_var;
} SomeName_t;
You need to do,
typedef struct somename {
struct somename some_var;
} SomeName_t;
Also, a struct cannot have a member which is an array of structure itself. However, a struct can have a member which is an array of pointer to the same structure.
struct foo {
struct foo foo_arr[10]; /* Will give error */
struct foo *foo_ptr_arr[10]; /* Legal */
};
However, I dont see a reason that your children member should be an array of struct anyways. Because, as can be seen in menu.c, you are doing
parent->children[parent->size] = child;
where the type of child is MenuItem_t *. So I think you basically wanted MenuItem_t.children to be an array of MenuItem_t *, and not an array of MenuItem_t.
So making this change should resolve your issue:
menu.h
typedef struct menuitem {
unsigned char size;
/* MenuItem_t children[10]; */ /* Not possible */
struct menuitem *children[10]; /* This is what you want to do */
struct menutem *parent;
} MenuItem_t;

Dereferencing pointer to incomplete type

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 ;

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*.

How to use struct within an union, within a struct in C?

i am currently having a lot of struggle with a, for me personally, very complex structure
struct crypto_tfm
{
uint32_t crt_flags;
union
{
struct ablkcipher_tfm ablkcipher;
struct aead_tfm aead;
struct blkcipher_tfm blkcipher;
struct cipher_tfm cipher;
struct hash_tfm hash;
struct compress_tfm compress;
struct rng_tfm rng;
} crt_u;
void (*exit)(struct crypto_tfm *tfm);
struct crypto_alg *crt_alg;
void *crt_ctx[] CRYPTO_MINALIGN_ATTR;
};
I completely have no idea how to use this struct. so basicly i am completely lost with this
the function using this expects a struct crypto_tfm *tfm
first idea is the following:
struct crypto_tfm *new_tfm()
{
struct crypto_tfm *tfm = malloc(sizeof(struct crypto_tfm));
tfm -> crt_flags = 0;
tfm -> crt_u.
}
but i dont know how to get further,
the given structs within the union are also using another structs. kinda too complicated for me right now
This is untested, but should be a good example:
struct st_a
{
int a;
};
struct st_b
{
int b;
};
union un_c
{
struct st_a aa;
struct st_b bb;
};
struct st_d
{
int d;
union un_c cc;
};
int main ()
{
struct st_d *dd = malloc (sizeof (struct st_d));
dd->d = 0;
/* The following two lines might (probably are) accessing
the same area of memory. */
dd->cc.aa.a = 0;
dd->cc.bb.b = 1;
}

Resources