static array initializer during structure initialization - c

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

Related

How To Initialize a C Struct using a Struct Pointer and Designated Initialization

How can I use struct pointers with designated initialization? For example, I know how to init the struct using the dot operator and designated initialization like:
person per = { .x = 10,.y = 10 };
But If I want to do it with struct pointer?
I made this but it didn't work:
pper = (pperson*){10,5};
If pper is a person * that points to allocated memory, you can assign *pper a value using a compound literal, such as either of:
*pper = (person) { 10, 5 };
*pper = (person) { .x = 10, .y = 5 };
If it does not already point to allocated memory, you must allocate memory for it, after which you can assign a value:
pper = malloc(sizeof *pper);
if (!pper)
{
fputs("Error, unable to allocate memory.\n", stderr);
exit(EXIT_FAILURE);
}
*pper = (person) { 10, 5 };
or you can set it to point to an existing object:
pper = &SomeExistingPerson;
A compound literal looks like a a cast of a brace-enclosed initializer list. Its value is an object of the type specified in the cast, containing the elements specified in the initializer. Here is a reference.
For a struct pperson, for instance, it would look like the following:
#include <stdio.h>
#include <malloc.h>
struct pperson
{
int x, y;
};
int main()
{
// p2 is a pointer to structure pperson.
// you need to allocate it in order to initialize it
struct pperson *p2;
p2 = (struct pperson*) malloc( sizeof(struct pperson));
*p2 = (struct pperson) { 1, 2 };
printf("%d %d\n", p2->x, p2->y);
// you may as well intiialize it from a struct which is not a pointer
struct pperson p3 = {5,6} ;
struct pperson *p4 = &p3;
printf("%d %d\n", p4->x, p4->y);
free(p2);
return 0;
}
You can use a pointer to a compound literal:
struct NODE{
int x;
int y;
}
struct NODE *nodePtr = &(struct NODE) {
.x = 20,
.y = 10
};
Notice that compund literals were introduced in C99.

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

Cost of nested dereferencing negligible?

I have a family of large recursive functions that operate on trees. These trees are defined using "polymorphism", like so
struct foo {
enum abctype type;
union {
struct a ay;
struct b bee;
struct c cee;
}
};
where struct a... c are all nodes in the tree. Each node in the tree (i.e., any object of type struct a... c), points to an object of struct foo. For example:
struct a {
/* definitions */
/*...*/
struct foo *next;
};
Because of this, the struct dereferences end up getting very nested even though my functions aren't overreaching their purposes.
In this case, the nested dereferences are inevitable. It would be absurd to write cute little wrapper functions just to get rid of a ->. But, I've heard many programmers say that you shouldn't go past 3-4 dereferences or your "algorithm needs fixing".
So, what's the verdict? Does my code need fixing? are nested dereferences inefficient?
Edit:
Here's what my data structure looks like in more depth (they're not trees, as I have been told, unless linked list == tree):
struct a {
/* definitions */
/*...*/
struct foo *longitudinal;
};
struct b {
/* definitions */
/*...*/
struct foo *longitudinal;
struct b *transverse;
};
struct c {
/* definitions */
/*...*/
struct foo *longitudinal;
struct c *transverse;
};
Basically, the data structures are this way because the data they handle is organized this way (in my head). I just don't see a way to convert this to a binary tree.
A single pointer does not make a tree; it makes a list. Trees require at least two pointers. (You can find exceptions described at Wikipedia, but it is unlikely — though not impossible — that you're intending to use such an organization for your tree structure.)
I think your data organization is … well, if it is not wrong, then it is at least sub-optimal. You should almost certainly be using a structure more like:
struct tree
{
struct tree *left;
struct tree *right;
enum abctype type;
union {
struct a aye;
struct b bee;
struct c cee;
};
};
Where each of the single-letter structure types contains only the relevant (variant) data and not any tree-related pointers:
struct a
{
/* definitions */
/* …no struct tree *next; or anything similar… */
};
The tree traversal is now nice and uniform. Compare what used to be necessary with what is now necessary. Given the old struct foo *tp, your original code (probably) needed to do ghastly stuff like:
if (tp->type == TYPE_A)
process_next(tp->ay.next);
else if (tp->type == TYPE_B)
process_next(tp->bee.next);
else if (tp->type == TYPE_C)
process_next(tp->cee.next);
else
…report error…
(and similarly with a prev or left and right pointers, or whatever else you used to create an actual tree structure — though even as a list, this is more than a trifle messy).
With the revised scheme, given a struct tree *tp;, you now just use:
process_tree(tp->left);
process_data(tp);
process_tree(tp->right);
The data handling has to deal with the enumeration and accessing the appropriate portion of the anonymous union. This is much the same as before (except you don't need to futz with the tree structure pointers).
Working code
I observe that since you've not shown data for the structures a, b, and c, I've had to guess at what might be appropriate. If that sort of detail matters to you, it is important that you put that information in the question before people get to answer it. (That means, in part, don't go adding data fields to the structures now — you've already blown the opportunity to specify what is in them.)
This code works, more or less. The memory management doesn't have memory access errors, at least with the test data. The data isn't freed; that's an exercise for you to play with. Not all the error checking that should be there is there; that's another exercise for you. And the testing isn't all that comprehensive — guess what that means?
There could be some confusion about how your data structure is supposed to work. I've interpreted it as:
You can have a (longitudinal) list of items in arbitrary order, of type A, B or C. These are stored via struct foo, complete with the anonymous union.
Items of type B can have a transverse list of more type B items.
Items of type C can have a transverse list of more type C items.
Here's some code that works:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct a
{
char name[20];
};
struct b
{
double x;
double y;
struct b *transverse;
};
struct c
{
int height;
int width;
int depth;
struct c *transverse;
};
enum abctype { TYPE_A, TYPE_B, TYPE_C };
struct foo
{
struct foo *longitudinal;
enum abctype type;
union
{
struct a aye;
struct b bee;
struct c cee;
};
};
static struct foo *add_a_long(struct foo *head, const char *name)
{
struct foo *new_foo = malloc(sizeof(*new_foo));
if (new_foo != 0)
{
strncpy(new_foo->aye.name, name, sizeof(new_foo->aye.name)-1);
new_foo->aye.name[sizeof(new_foo->aye.name)-1] = '\0';
new_foo->type = TYPE_A;
new_foo->longitudinal = head;
}
return new_foo;
}
static struct foo *add_b_long(struct foo *head, double x, double y)
{
struct foo *new_foo = malloc(sizeof(*new_foo));
if (new_foo != 0)
{
new_foo->bee.x = x;
new_foo->bee.y = y;
new_foo->bee.transverse = 0;
new_foo->type = TYPE_B;
new_foo->longitudinal = head;
}
return new_foo;
}
static struct foo *add_c_long(struct foo *head, int height, int width, int depth)
{
struct foo *new_foo = malloc(sizeof(*new_foo));
if (new_foo != 0)
{
new_foo->cee.height = height;
new_foo->cee.width = width;
new_foo->cee.depth = depth;
new_foo->cee.transverse = 0;
new_foo->type = TYPE_C;
new_foo->longitudinal = head;
}
return new_foo;
}
static void add_b_trans(struct b *b, double x, double y)
{
struct b *new_b = malloc(sizeof(*new_b));
if (new_b != 0)
{
new_b->x = x;
new_b->y = y;
new_b->transverse = 0;
while (b->transverse != 0)
b = b->transverse;
b->transverse = new_b;
}
}
static void add_c_trans(struct c *c, int height, int width, int depth)
{
struct c *new_c = malloc(sizeof(*new_c));
if (new_c != 0)
{
new_c->height = height;
new_c->width = width;
new_c->depth = depth;
new_c->transverse = 0;
while (c->transverse != 0)
c = c->transverse;
c->transverse = new_c;
}
}
static void print_foo(const char *tag, const struct foo *head)
{
printf("\n%s:\n", tag);
while (head != 0)
{
switch (head->type)
{
case TYPE_A:
printf("A: %s\n", head->aye.name);
break;
case TYPE_B:
{
const struct b *bp = &head->bee;
printf("B-main: (%f,%f)\n", bp->x, bp->y);
while ((bp = bp->transverse) != 0)
printf("B-trans: (%f,%f)\n", bp->x, bp->y);
}
break;
case TYPE_C:
{
const struct c *cp = &head->cee;
printf("C-main: (%d,%d,%d)\n", cp->height, cp->width, cp->depth);
while ((cp = cp->transverse) != 0)
printf("C-trans: (%d,%d,%d)\n", cp->height, cp->width, cp->depth);
}
break;
}
head = head->longitudinal;
}
}
int main(void)
{
struct foo *head = 0;
head = add_a_long(head, "Caterpillar");
print_foo("1 item", head);
head = add_a_long(head, "Ununtrium");
print_foo("2 items", head);
head = add_b_long(head, 1.00000, 1.00000);
head = add_b_long(head, 3.14159, 2.78128);
print_foo("4 items", head);
assert(head->type == TYPE_B);
add_b_trans(&head->bee, 1.2345, 2.3456);
add_b_trans(&head->bee, 9.8765, 6.5432);
print_foo("4 items, 2 transverse B", head);
head = add_a_long(head, "Ununpentium");
head = add_c_long(head, 3, 4, 5);
head = add_c_long(head, 5, 12, 13);
print_foo("6 items", head);
assert(head->type == TYPE_C);
add_c_trans(&head->cee, 7, 20, 27);
add_c_trans(&head->cee, 9, 35, 36);
head = add_a_long(head, "Ununseptium");
head = add_a_long(head, "Ununoctium");
print_foo("Final", head);
return 0;
}
And this is the sample output I get:
1 item:
A: Caterpillar
2 items:
A: Ununtrium
A: Caterpillar
4 items:
B-main: (3.141590,2.781280)
B-main: (1.000000,1.000000)
A: Ununtrium
A: Caterpillar
4 items, 2 transverse B:
B-main: (3.141590,2.781280)
B-trans: (1.234500,2.345600)
B-trans: (9.876500,6.543200)
B-main: (1.000000,1.000000)
A: Ununtrium
A: Caterpillar
6 items:
C-main: (5,12,13)
C-main: (3,4,5)
A: Ununpentium
B-main: (3.141590,2.781280)
B-trans: (1.234500,2.345600)
B-trans: (9.876500,6.543200)
B-main: (1.000000,1.000000)
A: Ununtrium
A: Caterpillar
Final:
A: Ununoctium
A: Ununseptium
C-main: (5,12,13)
C-trans: (7,20,27)
C-trans: (9,35,36)
C-main: (3,4,5)
A: Ununpentium
B-main: (3.141590,2.781280)
B-trans: (1.234500,2.345600)
B-trans: (9.876500,6.543200)
B-main: (1.000000,1.000000)
A: Ununtrium
A: Caterpillar
The canonical way to go about this is to really use the structs like derived classes. I. e.:
struct base {
enum abctype type;
};
struct a {
struct base super;
//whatever other data members `a` happens to have
};
With this approach, you write functions taking a struct base*, which is subsequently cast to one of the subclasses once. Further manipulation of the object uses the derived class pointer with only a single ->.
Btw: If you include a function pointer within struct base, you can directly call the derived class's function (no switch required). Bonus points for grouping the function pointers in a struct of their own (instanciated as global tables), with a single pointer in struct base pointing to the correct function table. That would very, very close to what C++ does under the hood...
struct base_vtable {
void (*foo)(int, double);
int (*bar)(struct base*);
int (*baz)();
};
struct a_vtable {
struct base_vtable super;
double (*bim)();
dobule (*bam)();
};
struct base {
struct base_vtable vtable;
};
struct a {
struct base super;
//whatever
};
And then, somewhere in a .c file:
static struct a_vtable g_a_vtable = {
.super.foo = &a_foo,
.super.bar = &a_bar,
.super.baz = &a_baz,
.bim = a_bim,
.bam = a_bam
};
struct a* a_create(...) {
struct a* me = malloc(sizeof(*me));
me->super->vtable = g_a_vtable;
//further initialization
};

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