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
Related
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;
I've written this code with all correct understandings i have. please check my problems.
#include<stdio.h>
#include<stdlib.h>
// Define a structure for the dequeue elements
This structure is all good, with data, next, previous pointers.
typedef struct RanElmt_ {
void *data;
struct DeqElmt_ *prev;
struct DeqElmt_ *next;
void (*destroy)(void *data);
//Your Code here
} RanElmt;
THis is ok too, acording to what i think is correct.
typedef struct RandQ_{
int size;
struct RanElmt *head;
struct RanElmt *tail;
}RandQ;
RandQ * RandomizedQueue(void (*destroy)(void *data)){
RandQ *relmt = (RandQ*)malloc(sizeof(RandQ));
} // construct an empty randomized queue
int isREmpty(RandQ *rQ){
if ( rQ->size == 0)
return 1;
return 0;
} // is the queue empty?
int rsize(RandQ *rQ){
return rQ->size;
}
// return the number of items on the queue
ACtually this is only one function,(enqueue) I'm going to get the idea and code other functions(dequeue, sample etc..)
int enqueue(RandQ *rQ, const void *data){
RanElmt *relmt = (RanElmt*)malloc(sizeof(RanElmt));
relmt->data = (void*)data;
if (rQ->head == NULL){
relmt = rQ->head;
relmt = rQ->tail;
relmt->prev = NULL;
relmt->next = NULL;
}
else{
rQ->head = relmt;
}
(rQ->head)->prev = relmt;
relmt->prev = rQ->head;
rQ->head = relmt;
} // add the item
main(){
Deque(free);
printf(" okk \n");
}
THis program is giving these errors:
Errors i'm getting
In C struct tags and type names live in different name spaces. That is struct RanElmt and RanElmt are two different types, in addition struct RanElmt is not completely defined.
Your RandQ should be defined something like
typedef struct RandQ_{
int size;
struct RanElmt_ *head; // or RanElmt* head;
struct RanElmt_ *tail; // or RanElmt* tail;
}RandQ;
in addition your RanElmt is probably not what you want, maybe you meant:
typedef struct RanElmt_ {
void *data;
struct RanElmt_ *prev; // pointer to a struct of the same type
struct RanElmt_ *next; // pointer to a struct of the same type
void (*destroy)(void *data);
// You cannot put code here in C (or even a function definition AFAIK).
} RanElmt;
You have confused the struct tag and the typedeffed alias for the queue elements in the definition of the queue:
typedef struct RandQ_{
int size;
struct RanElmt *head;
struct RanElmt *tail;
} RandQ;
Here, the head and tail are of the type struct RanElmt. This struct doesn't exist in your program. You have a struct RanElmt_ (with trailing underscore) that you can also call ´RanElmtwithout thestructkeyword, because you have combined the struct definition with atypedef`.
The compiler still generates the code, because pointers to unknown structs are okay, unless you try to get at their data. Obviously the compiler can't access the struct fields if it doesn't know them.
There's no need for the underscore. The names of structs are in a separate namespace, so you can have both a struct called RandQ and a type (in global namespace) called RanQ. I recommend to use the same name for struct tag and aliassed type.
You can also get rid of the need to use the struct keyword inside the struct defnition if you separate the typedef from the struct definition:
typedef struct RanElmt RanElmt; // use just RanElmt from now on
struct RanElmt {
void *data;
RanElmt *prev;
RanElmt *next;
} RanElmt;
Your code has several other problems, but I think he program is in an early state, so I don't address them here.
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 ;
I'm working with C. Can you tell me if this is the right way to allocate memory for a struct which contains a string?
struct _TipoLista {
char info[10];
struct _TipoLista *next;
};
typedef struct _TipoLista *TipoLista;
...
TipoLista el;
el = malloc(sizeof(TipoLista));
If a try to create a list in this way, I always get errors when I try to insert the 2nd element while. However, if I change "info" from char[10] to an int my code always works.
el = malloc(sizeof(*el));
or
el = malloc(sizeof(struct _TipoLista));
or initializing while declaring the struct
struct _TipoLista {
char info[10];
struct _TipoLista *next;
}obj1;
In the first two cases it's dynamic memory allocation 3rd is static memory allocation
el = malloc(sizeof(*el));
TipoLista has size of a pointer so that's not what you really want.
You should try the following
el = malloc(sizeof(struct _TipoLista));
Or define a typedef for this structure.
You are trying to do a typedef i.e., an alias for the strucuture. Typedef in turn means that "from this point onwards *struct _TipoLista* will be called as *TipoLista "
If you want to have a linked list of type "struct _TipoLista", then this could help.
struct _TipoLista {
char info[10];
struct _TipoLista *next;
};
typedef struct _TipoLista TipoLista;
int main()
{
TipoLista *Tptr = malloc(sizeof(TipoLista) );
/** Rest is history */
}
Hope this can be useful:
typedef struct {
char info[10];
struct _TipoLista *next;
} TipoLista;
TipoLista* construct_lista()
{
TipoLista* ret = malloc(sizeof(TipoLista));
ret->next = NULL;
return ret;
}
void destruct_lista(TipoLista* lista)
{
TipoLista* next;
while (lista != NULL)
{
next = lista->next;
free(lista);
lista=next;
}
}
void insert_into_list(TipoLista* lista, char* element)
{
while (lista->next != NULL)
lista = lista->next;
lista->next = construct_lista();
strcpy(lista->next->info, element);
}
I bumped into this error when I was trying to access a field in my defined struct:
struct linkNode{
struct linkNode *next;
char *value;
};
In the header file I defined a type called linkNode_t:
typedef struct linkNode linkNode_t;
When I tried to use this struct in the main of another file, everything else was fine except when I tried to do
linkNode_t* currentpath = /*a pointer to a struct of type linkNode_t*/
int something = strlen(currentpath->value);/****ERROR*****/
Compiler gave me the incomplete type error. Am I declaring the struct properly?
Struct has to be declared in header, before you do typedef. You can combine both:
typedef struct linkNode {
struct linkNode *next;
char *value;
} linkNode_t;
As the others pointed out, it's generally better to put your "typedef" and your struct definition all in the same place.
But that isn't required, and that's not the problem.
This test case compiles and runs correctly:
#include <stdio.h>
#include <string.h>
#define NULL 0
struct linkNode{
struct linkNode *next;
char *value;
};
typedef struct linkNode linkNode_t;
linkNode_t rec = {
NULL,
"abcdef"
};
int
main (int argc, char *argv[])
{
linkNode_t* currentpath = &rec;
int something = strlen(currentpath->value);
printf ("sizeof (rec)= %d, currentpath->value= %s, something= %d...\n",
sizeof (rec), currentpath->value, something);
return 0;
}
ACTUAL PROBLEM AND SOLUTION:
1) You're doing all the right stuff.
2) Just make sure you put your "typedef" AFTER (or, at least, as part of) your struct definition:
struct linkNode{
...
};
typedef struct linkNode linkNode_t;
struct linkNode{
struct linkNode *next;
char *value;
};
This is incomplete because you cannot use struct directly inside the structure.
You should use
typedef struct linkNode{
struct linkNode *next;
char *value;
}new_name;