structs in C with initial values [duplicate] - c

Is it possible to set default values for some struct member?
I tried the following but, it'd cause syntax error:
typedef struct
{
int flag = 3;
} MyStruct;
Errors:
$ gcc -o testIt test.c
test.c:7: error: expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘=’ token
test.c: In function ‘main’:
test.c:17: error: ‘struct <anonymous>’ has no member named ‘flag’

Structure is a data type. You don't give values to a data type. You give values to instances/objects of data types.
So no this is not possible in C.
Instead you can write a function which does the initialization for structure instance.
Alternatively, You could do:
struct MyStruct_s
{
int id;
} MyStruct_default = {3};
typedef struct MyStruct_s MyStruct;
And then always initialize your new instances as:
MyStruct mInstance = MyStruct_default;

you can not do it in this way
Use the following instead
typedef struct
{
int id;
char* name;
}employee;
employee emp = {
.id = 0,
.name = "none"
};
You can use macro to define and initialize your instances. this will make easiier to you each time you want to define new instance and initialize it.
typedef struct
{
int id;
char* name;
}employee;
#define INIT_EMPLOYEE(X) employee X = {.id = 0, .name ="none"}
and in your code when you need to define new instance with employee type, you just call this macro like:
INIT_EMPLOYEE(emp);

I agree with Als that you can not initialize at time of defining the structure in C.
But you can initialize the structure at time of creating instance shown as below.
In C,
struct s {
int i;
int j;
};
struct s s_instance = { 10, 20 };
in C++ its possible to give direct value in definition of structure shown as below
struct s {
int i;
s(): i(10) {}
};

You can do:
struct employee_s {
int id;
char* name;
} employee_default = {0, "none"};
typedef struct employee_s employee;
And then you just have to remember to do the default initialization when you declare a new employee variable:
employee foo = employee_default;
Alternatively, you can just always build your employee struct via a factory function.

Create a default struct as the other answers have mentioned:
struct MyStruct
{
int flag;
}
MyStruct_default = {3};
However, the above code will not work in a header file - you will get error: multiple definition of 'MyStruct_default'. To solve this problem, use extern instead in the header file:
struct MyStruct
{
int flag;
};
extern const struct MyStruct MyStruct_default;
And in the c file:
const struct MyStruct MyStruct_default = {3};
Hope this helps anyone having trouble with the header file.

If you are using gcc you can give designated initializers in object creation.
typedef struct {
int id = 0;
char *name = "none";
} employee;
employee e = {
.id = 0;
.name = "none";
};
Or , simply use like array initialization.
employee e = {0 , "none"};

Even more so, to add on the existing answers, you may use a macro that hides a struct initializer:
#define DEFAULT_EMPLOYEE { 0, "none" }
Then in your code:
employee john = DEFAULT_EMPLOYEE;

You can implement an initialisation function:
employee init_employee() {
empolyee const e = {0,"none"};
return e;
}

You can use combination of C preprocessor functions with varargs, compound literals and designated initializers for maximum convenience:
typedef struct {
int id;
char* name;
} employee;
#define EMPLOYEE(...) ((employee) { .id = 0, .name = "none", ##__VA_ARGS__ })
employee john = EMPLOYEE(.name="John"); // no id initialization
employee jane = EMPLOYEE(.id=5); // no name initialization

You can use some function to initialize struct as follows,
typedef struct
{
int flag;
} MyStruct;
MyStruct GetMyStruct(int value)
{
MyStruct My = {0};
My.flag = value;
return My;
}
void main (void)
{
MyStruct temp;
temp = GetMyStruct(3);
printf("%d\n", temp.flag);
}
EDIT:
typedef struct
{
int flag;
} MyStruct;
MyStruct MyData[20];
MyStruct GetMyStruct(int value)
{
MyStruct My = {0};
My.flag = value;
return My;
}
void main (void)
{
int i;
for (i = 0; i < 20; i ++)
MyData[i] = GetMyStruct(3);
for (i = 0; i < 20; i ++)
printf("%d\n", MyData[i].flag);
}

If you only use this structure for once, i.e. create a global/static variable, you can remove typedef, and initialized this variable instantly:
struct {
int id;
char *name;
} employee = {
.id = 0,
.name = "none"
};
Then, you can use employee in your code after that.

Another approach, if the struct allows it, is to use a #define with the default values inside:
#define MYSTRUCT_INIT { 0, 0, true }
typedef struct
{
int id;
int flag;
bool foo;
} MyStruct;
Use:
MyStruct val = MYSTRUCT_INIT;

An initialization function to a struct is a good way to grant it default values:
Mystruct s;
Mystruct_init(&s);
Or even shorter:
Mystruct s = Mystruct_init(); // this time init returns a struct

Another approach to default values. Make an initialization function with the same type as the struct. This approach is very useful when splitting large code into separate files.
struct structType{
int flag;
};
struct structType InitializeMyStruct(){
struct structType structInitialized;
structInitialized.flag = 3;
return(structInitialized);
};
int main(){
struct structType MyStruct = InitializeMyStruct();
};

You can create a function for it:
typedef struct {
int id;
char name;
} employee;
void set_iv(employee *em);
int main(){
employee em0; set_iv(&em0);
}
void set_iv(employee *em){
(*em).id = 0;
(*em).name = "none";
}

I think the following way you can do it,
typedef struct
{
int flag : 3;
} MyStruct;

Related

struct in c with an attribute that is a pointer to the same struct

i need to create a struct with an attribute that is a pointer to the same struct.
i'm trying this solution but not work:
typedef struct
{
int number;
void *other;
}mystruct;
extern mystruct first[];
extern mystruct second[];
mystruct first[] = {{1,NULL},{2,second}};
mystruct second[] = {{3,NULL},{4,first}};
mystruct *wrap;
wrap = (mystruct *)first[1].other;
int main(void){
printf("%d\n",first[0].number);
printf("%d\n",second[0].number);
printf("%d\n",wrap[1].number);
}
can someone help me?
best regards and thankyou
In C, you can name the struct before using it and typdefing it:
typedef struct mystruct_
{
int number;
struct mystruct_ *other;
} mystruct
I'm not entirely sure but are you looking for some sort of linked-lists or precisely speak Self Referential structure
struct list {
int something;
struct list *use_this_to_point_to_similar_type;
};
Here is another good reference what-is-self-referencing-structure-in-c
just a little bit simplification, and moving few instructions here and there, below code is a loosely written example of possibly what you are looking forward to achieve
#include<stdio.h>
struct mystruct
{
int number;
struct mystruct *other;
};
struct mystruct first[] = {{1,NULL},{2,NULL}};
struct mystruct second[] = {{3,NULL},{4,NULL}};
struct mystruct *wrap;
int main(void)
{
first[1].other = second;
second[1].other = first;
wrap = first[1].other;
printf("%d\n",first[0].number);
printf("%d\n",second[0].number);
printf("%d\n",wrap[1].number);
return 0;
}
your first and second don't need to be extern as they are allocated within your program. you can declare and init. var prior to the main. but the rest you must move into the main function:
int main(void){
wrap = (first[1].other);
printf("%d\n",first[0].number);
printf("%d\n",first[1].number);
printf("%d\n",second[0].number);
printf("%d\n",wrap[1].number);
return 0;}

Declare struct inside main()

I am new to C. I got asked to modify this program so that the variables student and anotherStudent are not global but are local to main.It will still be printed by printStudnets. typedef is not allowed to use.
I understand if declare struct in main and it would be ascessible to the main function only.Do I have to declare struct in each function to achieve this?
#include <stdio.h>
#include <stdlib.h>
struct student_s {
char* name;
int age;
struct student_s* next;
} student;
struct student_s anotherStudent;
void printOneStudent(struct student_s student)
{
printf("%s (%d)\n", student.name, student.age);
}
void printStudents(const struct student_s* student)
{
while (student != NULL) {
printOneStudent(*student);
student = student->next;
}
}
int main(void)
{
student.name = "Agnes McGurkinshaw";
student.age = 97;
student.next = &anotherStudent;
anotherStudent.name = "Jingwu Xiao";
anotherStudent.age = 21;
anotherStudent.next = NULL;
printStudents(&student);
return EXIT_SUCCESS;
}
You don't need to use typedef in order to define a new structured type. This is perfectly valid:
struct student_s {
char* name;
int age;
struct student_s* next;
}; // Remove "student". Now you don't have a global variable.
A consequence of this is that student_s is not a name of your structured type; it is a tag of your structured type. Therefore, declaring objects of structured type corresponding to student_s must start with the keyword struct:
int main(void)
{
struct student_s student;
... // The rest of your code remains the same
}

Confused about updating a struct member in C

It has been a LONG time (25y) since I have done C and so I forget some things so please forgive the question.
Given that I have the following declarations:
typedef struct item {
int field;
} Item;
typedef struct data {
Item b;
} Data;
I have been trying to update the struct when its passed to a function and this doesn't work at all.
static void foo(Data *data) {
data->b.field = 3; // doesn't work, the struct remains unchanged.
}
static void test() {
Data v = {.b = {.field = 2}};
foo(&v);
}
However, if I alter the declaration slightly, use malloc to allocate it it works.
typedef struct data {
Item *b;
};
static void foo(struct data *data) {
data->b->field = 3; // works.
}
static void test() {
Data v = (struct data*) malloc(sizeof(Data));
Item i = (struct item*) malloc(sizeof(Item));
foo(v);
free(i);
free(v);
}
Can someone inform me why this is? Is it not possible to have struct members that are updatable as members? How could I make the first example work?
Thanks in advance.
Your first approach actually works (and I would have been surprised if it did not):
struct item {
int field;
};
struct data {
struct item b;
};
static void foo(struct data *data) {
data->b.field = 3;
}
static void test() {
struct data v = {.b = {.field = 2}};
printf("v.b.field before calling foo: %d\n", v.b.field);
foo(&v);
printf("v.b.field afterwards: %d\n", v.b.field);
}
int main() {
test();
}
Output:
v.b.field before calling foo: 2
v.b.field afterwards: 3
Probably your setting is a different one that than you've shown in the code. Mysterious things (i.e. undefined behaviour) often happens if you access an object after it's lifetime has ended. malloc often prevents such issues as it keeps an object alive until it is explicitly freed.
But in your case, there should not be any difference.
BTW: the typedef does not make sense, as you do not define an alias for the struct-type just declared. So
struct item {
int field;
};
is sufficient.

Nested struct initialization with structs

maybe this is a duplicate but I can't find a proper solution for this problem... and I'm sort of being new to C development, and my problem is that I don't know how to initialized a nested struct, take a look for more info...
So the thing is the following:
// another_struct.h
struct AnotherStruct {
void (*some_function)();
}
extern struct AnotherStruct AnotherStruct;
// yet_another_struct.h
struct YetAnotherStruct {
void (*some_function)();
}
extern struct YetAnotherStruct YetAnotherStruct;
// my_struct.h
struct MyStruct1 {
struct AnotherStruct another;
struct YetAnotherStruct and_yet;
}
extern struct MyStruct1 MyStruct1;
In their respective .C file:
struct AnotherStruct AnotherStruct = {
.some_function = blabla
};
struct YetAnotherStruct YetAnotherStruct = {
.some_function = blablabla
};
// I want the initialization of MyStruct1 to have the struct pointing to the structs
struct MyStruct1 MyStruct1 = { /* ?? */ };
/* I was thinking something like this */
struct MyStruct1 MyStruct1 = {
.another = AnotherStruct,
.and_yet = YetAnotherStruct
};
But the compiler complains xD
So my ultimate goal is to be able access the child structures as:
MyStruct1.another.some_function();
Thanks a lot and sorry if this question is duplicate or is way to noob :)
Why don't you construct them like this (No pointer usage):
/* I was thinking something like this */
struct MyStruct1 MyStruct1 = {
.another = { //.another is your struct, just do construct like normal
.some_function = blabla
},
.and_yet = { //The same here.
.some_function = blablabla
}
};
Usage in your code is:
//Call function
MyStruct1.another.some_function();
Using pointers:
// my_struct.h, add pointers
struct MyStruct1 {
struct AnotherStruct *another; //Added pointers
struct YetAnotherStruct *and_yet; //Here too
}
and then use in your .c
struct AnotherStruct AnotherStruct = {
.some_function = blabla
};
struct YetAnotherStruct YetAnotherStruct = {
.some_function = blablabla
};
/* I was thinking something like this */
struct MyStruct1 MyStruct1 = {
.another = &AnotherStruct, //Added & for address
.and_yet = &YetAnotherStruct //Added & for address
};
And later access to your values like:
//Call your function now
MyStruct1.another->some_function();
#tilz0R not enough rep to comment. A little modification to your answer.
typedef struct {
int a_val;
} A;
typedef struct {
float b_val;
} B;
typedef struct {
A *a;
B *b;
} C;
C c = {
.a = &(A){ .a_val = 1 },
.b = &(B){ .b_val = 1. },
};
As for union thingie, probably it is about Microsoft extension syntax
typedef struct {
A;
B;
} C;
C c;
c.a_val = 1; // valid
Unfortunately this one is a non standard extension, moreover it is doomed to never become one since this was a committee decision to maintain compatibility with C++.
Per #Lundin comment. The following code is indeed possible in modern C:
typedef struct {
struct {
int a_val;
};
struct {
float b_val;
};
} C;
C c;
c.a_val = 1;
However this brings little to no benefit (apart from organizing your code) in case of embedding structures into structures. It is pretty cool than it comes to unions though:
typedef struct {
enum {
TA,
TB
} _;
union {
struct {
int a;
};
struct {
float b;
};
};
} C;
C c = { ._ = TA, .a = 1 };
Used compile line:
gcc -std=c11 -Wall -Wextra -pedantic

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;

Resources