Nested struct initialization with structs - c

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

Related

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

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

static array initializer during structure initialization

Here is a simplified version of two structs I have:
struct MyStruct1 {
double d;
}
struct MyStruct2 {
struct MyStruct1* a;
int i;
}
I can initialize the second struct as follows:
void InitStruct(struct MyStruct2 pMyStruct2) {
static struct MyStruct1 A[] = { {.d=12} , {.d=17} , {.d=1} };
*pMyStruct2 = (struct MyStruct2) { .a = A, .i = 3 };
}
but actually I have to initialize it this way (its because this struct is again part of a bigger structure that shall be initialized at once):
void InitStruct(struct MyStruct2 pMyStruct2) {
*pMyStruct2 = (struct MyStruct2) {
.a = (struct MyStruct1[]) {
{.d=12} , {.d=17} , {.d=1}},
.i=3 };
}
Both ways compile without any warnings but the data in the second solution gets corrupted.
I think that the inner array is not static and thus the .a-pointer gets invalid immediately.
Is there another way to tell the compiler to keep the data of the array in the memory?
C99 standard §6.5.2.5 p6 says that:
The value of the compound literal is that of an unnamed object
initialized by the initializer list. If the compound literal occurs
outside the body of a function, the object has static storage
duration; otherwise, it has automatic storage duration associated with
the enclosing block.
In both cases the varables should be properly initialized and valid for usage in the scope they are declared.
If you, however, return the structure from the function by value, the pointer will become invalid.
Here is a sample code I used for testing. Valgrind shows no errors.
#include <stdio.h>
struct MyStruct1 {
double d;
};
struct MyStruct2 {
struct MyStruct1* a;
int i;
};
struct MyStruct1 A[] = { {.d=12} , {.d=17} , {.d=1} };
struct MyStruct2 b1 = { .a = A, .i = 3 };
struct MyStruct2 b2 = { .a = (struct MyStruct1[]) {
{.d=12} , {.d=17} , {.d=1}
},
.i=3 };
int main( void ) {
struct MyStruct1 B[] = { {.d=12} , {.d=17} , {.d=1} };
struct MyStruct2 b3 = { .a = B, .i = 3 };
struct MyStruct2 b4 = { .a = (struct MyStruct1[]) {
{.d=12} , {.d=17} , {.d=1}
},
.i=3 };
printf("b1->a.d=%1.2f\n", b1.a->d);
printf("b2->a.d=%1.2f\n", b2.a->d);
printf("b3->a.d=%1.2f\n", b3.a->d);
printf("b4->a.d=%1.2f\n", b4.a->d);
}

structs in C with initial values [duplicate]

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;

How to initialize a const variable inside a struct in C?

I write a struct
struct Tree{
struct Node *root;
struct Node NIL_t;
struct Node * const NIL; //sentinel
}
I want
struct Node * const NIL = &NIL_t;
I can't initialize it inside the struct.
I'm using msvs.
I use C, NOT C++.
I know I can use initialization list in C++.
How to do so in C?
If you are using C99, you can used designated initializers to do this:
struct Tree t = { .root = NULL, .NIL = &t.NIL_t };
This only works in C99, though. I've tested this on gcc and it seems to work just fine.
For those seeking a simple example, here it goes:
#include <stdio.h>
typedef struct {
const int a;
const int b;
} my_t;
int main() {
my_t s = { .a = 10, .b = 20 };
printf("{ a: %d, b: %d }", s.a, s.b);
}
Produces the following output:
{ a: 10, b: 20 }
A structure defines a data template but has no data itself. Since it has no data, there's no way to initialize it.
On the other hand, if you want to declare an instance, you can initialize that.
struct Tree t = { NULL, NULL, NULL };
Maybe something like this will suffice?
struct {
struct Node * const NIL;
struct Node *root;
struct Node NIL_t;
} Tree = {&Tree.NIL_t};

Resources