Initializing a Struct of a Struct - c

If I have a struct in C that has an integer and an array, how do I initialize the integer to 0 and the first element of the array to 0, if the struct is a member another struct so that for every instance of the other struct the integer and the array has those initialized values?

Initialisers can be nested for nested structs, e.g.
typedef struct {
int j;
} Foo;
typedef struct {
int i;
Foo f;
} Bar;
Bar b = { 0, { 0 } };

I hope this sample program helps....
#include <stdio.h>
typedef struct
{
int a;
int b[10];
}xx;
typedef struct
{
xx x1;
char b;
}yy;
int main()
{
yy zz = {{0, {1,2,3}}, 'A'};
printf("\n %d %d %d %c\n", zz.x1.a, zz.x1.b[0], zz.x1.b[1], zz.b);
return 0;
}
yy zz = {{0, {0}}, 'A'}; will initialize all the elements of array b[10] will be set to 0.
Like #unwind suggestion, In C all instances created should initialized manually. No constructor kind of mechanism here.

You can 0-initialize the whole struct with {0}.
For example:
typedef struct {
char myStr[5];
} Foo;
typedef struct {
Foo f;
} Bar;
Bar b = {0}; // this line initializes all members of b to 0, including all characters in myStr.

C doesn't have constructors, so unless you are using an initializer expression in every case, i.e. write something like
my_big_struct = { { 0, 0 } };
to initialize the inner structure, you're going to have to add a function and make sure it's called in all cases where the structure is "instantiated":
my_big_struct a;
init_inner_struct(&a.inner_struct);

Here is an alternative example how you would do things like this with object-oriented design. Please note that this example uses runtime initialization.
mystruct.h
#ifndef MYSTRUCT_H
#define MYSTRUCT_H
typedef struct mystruct_t mystruct_t; // "opaque" type
const mystruct_t* mystruct_construct (void);
void mystruct_print (const mystruct_t* my);
void mystruct_destruct (const mystruct_t* my);
#endif
mystruct.c
#include "mystruct.h"
#include <stdlib.h>
#include <stdio.h>
struct mystruct_t // implementation of opaque type
{
int x; // private variable
int y; // private variable
};
const mystruct_t* mystruct_construct (void)
{
mystruct_t* my = malloc(sizeof(mystruct_t));
if(my == NULL)
{
; // error handling needs to be implemented
}
my->x = 1;
my->y = 2;
return my;
}
void mystruct_print (const mystruct_t* my)
{
printf("%d %d\n", my->x, my->y);
}
void mystruct_destruct (const mystruct_t* my)
{
free( (void*)my );
}
main.c
int main (void)
{
const mystruct_t* x = mystruct_construct();
mystruct_print(x);
mystruct_destruct(x);
return 0;
}
You don't necessarily need to use malloc, you can use a private, statically allocated memory pool as well.

Related

Pointer in const C struct

Assuming that the following structures exist...
typedef struct MyFirstStruct
{
uint8_t someContent;
}
typedef struct MySecondStruct
{
MyFirstStruct* firstStructs;
uint8_t firstStructCount;
}
... and a function gets the following Parameter.
const MySecondStruct* const secondStruct
Is it allowed to change any value?
I am sure that this is not correct:
secondStruct->firstStructCount++.
But neither the Compiler nor PC-Lint complains about secondStruct->firstStructs->someContent++.
Is it allowed to do Change someContent because firstStructs is not const or is the behavior undefined?
Thanks!
The values of the nested struct(s) firstStructs can change as long as the pointer does not change. The constness of the pointer prevents the pointer value from changing, but the constness of the struct only means that its values must not change (i.e. the value of the pointer and the count).
You can modify the struct(s) pointed to by firstStructs arbitrarily without changing the pointer. You can also clearly see from the struct definition that this is legal, because firstStructs is a pointer to struct MyFirstStruct, not a pointer to const struct MyFirstStruct.
Here is an example to understand the principle without the const-pointer to const elements:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int x;
} Simple;
typedef struct {
Simple* s;
int scount;
} Nested;
int main()
{
Nested x;
x.scount = 10;
x.s = malloc(sizeof(Simple) * x.scount);
const Nested n = x;
for (int i = 0; i < n.scount; ++i)
{
n.s[i].x = i;
printf("%d\n", n.s[i].x);
}
}
It is OK and it was easy to check yourself:
typedef struct
{
uint8_t someContent;
} MyFirstStruct;
typedef struct
{
MyFirstStruct* firstStructs;
uint8_t firstStructCount;
}MySecondStruct;
MyFirstStruct fs;
MySecondStruct str = {.firstStructs = &fs};
const MySecondStruct* const secondStruct = &str;
int main()
{
secondStruct->firstStructs->someContent++;
}
but did not as the posted code was full of syntax errors.
You cant of course change the pointer itself:
This will give you errors:
typedef struct
{
uint8_t someContent;
} MyFirstStruct;
typedef struct
{
MyFirstStruct* firstStructs;
uint8_t firstStructCount;
}MySecondStruct;
MyFirstStruct fs[2];
MyFirstStruct ss;
MySecondStruct str = {.firstStructs = fs};
const MySecondStruct* const secondStruct = &str;
int main()
{
secondStruct->firstStructs++->someContent++;
secondStruct->firstStructs = &ss;
}

Macro that knows void * allocation type

Let have this code as example:
typedef struct {
int value;
char another;
} foo;
typedef struct {
float yet_another;
long really_another;
} bar;
typedef struct {
char* name;
void* data;
} gen;
int main(int argc, char** argv) {
gen foo_gen, bar_gen;
foo_gen.name = "Foo";
foo_gen.data = (foo*) malloc(sizeof(foo));
bar_gen.name = "Bar";
bar_gen.data = (bar*) malloc(sizeof(bar));
((foo*) foo_gen->data)->value = 0;
((bar*) bar_gen->data)->yet_another = 1.0f;
return 0;
}
This code would work ok, so I defined 2 macro to facilitate my work:
#define FOO_DATA(N, D) ((foo*) N->data)->D
#define BAR_DATA(N, D) ((bar*) N->data)->D
But it seems to be too repetitive. I want it to make more generic, making the macro to know which type it should cast. I tried using __auto_type:
#define DATA(N, D) (__auto_type N->data)->D
But it didn't work. It seems too that typeof don't works with macros. How should I do it?
If me and the other commenters understand correctly, you want to be able to do something like this:
struct a {
int field1;
} a;
struct b {
int field2;
} b;
void *self1 = &a;
void *self2 = &b;
int f1 = MAGIC(self1)->field1;
int f2 = MAGIC(self2)->field2;
for some definition of MAGIC.
This is not possible in C.
Expanding on my comment: you would have to group your common fields into another struct and make that the first field of the possible structs in self->data:
struct common {
int foo;
};
struct a {
struct common common;
int bar;
};
struct b {
struct common common;
int baz;
};
#define $(D) (((struct common*) self->data)->D)

Defining a program local pointer of a structure

my question deals with creating variables that are visible throughout the program file. In other words, a file-local variable.
Consider this example
#include <stdio.h>
struct foo
{
char s[] = "HELLO";
int n = 5;
};
struct foo *a;
int main()
{
puts("Dummy outputs!\n");
printf("%s\n",a->s);
printf("%d\n",a->n);
return 0;
}
Now, this code snippet won't run.
Why?
Because the structure pointed to be pointer variable a will not get allocated as the statement never executed.
Now, how do you get it allocated without changing the scope of this variable a?
#include <stdio.h>
struct foo {
char const *s;
int n;
};
/* static for file-local */
static struct foo a = { "HELLO" , 5 };
int main(void) {
printf("%s\n", a.s);
printf("%d\n", a.n);
return 0;
}
Now, how do you get it allocated without changing the scope of this variable a?
I am sure there a lot of ways to solve your problem. Here's my suggestion.
Change the definition of struct foo to contain a fixed number of characters in s.
Create a as an object instead of a pointer. Initialize it with the necessary values.
Make a a static variable so its use is limited to the file only.
Use the object a instead of the pointer a in rest of the file.
#include <stdio.h>
struct foo
{
char s[20];
int n;
};
static struct foo a = {"HELLO", 20};
int main()
{
puts("Dummy outputs!\n");
printf("%s\n",a.s);
printf("%d\n",a.n);
return 0;
}
This:
struct foo
{
char s[] = "HELLO";
int n = 5;
};
Is not valid C code. You first declare the type:
struct foo
{
char s[10];
int n;
};
Then define a variable of that type:
static struct foo a = { "HELLO", 5 };
The static keyword allows this variable to have file local scope.
You can now use it like this:
static struct foo a = { "HELLO", 5 };
void other()
{
puts("Dummy outputs!\n");
printf("%s\n",a.s);
printf("%d\n",a.n);
}
int main()
{
puts("Dummy outputs!\n");
printf("%s\n",a.s);
printf("%d\n",a.n);
other();
return 0;
}
Note that a is accessible from both functions. It will not however be viewable from functions defined in other files because it is declared as static.
As for using a pointer vs the struct directly, you can take the address of this structure at any time you need to use it in that way:
some_function(&a);
well, i need to use a pointer instead of a structure directly
Try this:
#include <stdio.h>
#include<string.h>
#include<stdlib.h>
struct foo{
char s[20];
int n;
};
int main(void){
struct foo *a;
a = malloc(sizeof(struct foo));
puts("Dummy outputs!\n");
strcpy(a->s, "HELLO");
a->n = 5;
printf("%s\n",a->s);
printf("%d\n",a->n);
free(a);
return 0;
}
Output:
Dummy outputs!
HELLO
5

Why the C structure definition in the implementation file is unavailable?

I give the following example to illustrate my question:
1) a.h where the structure is declared
a.h
struct A_Structure;
typedef struct A_Structure *A_Structure_Ptr;
2) b.c where the structure definition is implemented
#include "a.h"
struct A_Structure
{
int a;
int b;
int c;
};
2) main.c where the structure is invoked
#include <stdlib.h>
#include "a.h"
int main ()
{
struct A_Structure b;
return 0;
}
However, I cannot compile these C codes as I receive the following error message:
>main.c(6): error C2079: 'b' uses undefined struct 'A_Structure'
Any ideas? Thank in advance.
EDIT:
#include <stdlib.h>
#include "a.h"
int main ()
{
struct A_Structure *b=0;
b=(struct A_Structure*)malloc(12);
b->a=3;
free(b);
return 0;
}
I tried to create the structure in this way but still failed.
You probably need this:
struct A_Structure
{
int a;
int b;
int c;
};
in a.h
This is the typical approach when defining structs
If you're trying to implement an opaque pointer, you need a function that instantiates A_Structure and returns a pointer, as well as functions that manipulate A_Structure pointers:
in a.h
A_Structure_Ptr CreateA(int a, int b, int c);
void FreeA(A_Structure_Ptr obj);
void SetA_a( A_Structure_Ptr obj, int a );
int GetA_a( A_Structure_Ptr obj );
// etc.
in b.c
A_Structure_Ptr CreateA(int a, int b, int c)
{
A_Structure_Ptr s = malloc( sizeof(A_Structure) );
s->a = a;
s->b = b;
s->c = c;
}
void FreeA(A_Structure_Ptr obj)
{
free( obj );
}
void SetA_a( A_Structure_Ptr obj, int a )
{
obj->a = a;
}
in main.c
int main ()
{
struct A_Structure *b = CreateA( 1, 2, 3);
SetA_a( b, 3 );
FreeA(b);
return 0;
}
When you put the structure declaration in a header file, but leave the definition in the .c file, this is known as using an opaque pointer API.
In an API like this, consumers only use pointers to the objects. Only the implementation needs to know the size or contents of the object. This is how you do OOP in C, and is key to information hiding which provides better decoupling of components. Here's a more complete example:
foo.h
struct foo; // forward declaration
struct foo *foo_create(void);
void foo_use(struct foo *f);
void foo_destroy(struct foo *f);
foo.c
#include <stdlib.h>
#include "foo.h"
struct foo {
int a, b, c; // Consumers don't know about these!
};
struct foo *foo_create(void)
{
struct foo *f = malloc(sizeof(*f));
if (!f)
return NULL;
*f = (struct foo) {
.a = 1,
.b = 2,
.c = 3,
};
return f;
}
void foo_use(struct foo *f)
{
// something with f->a, f->b
}
void foo_destroy(struct foo *f)
{
free(f);
}
main.c
#include "foo.h"
int main(void)
{
struct foo *f; // As a consumer of foo, we can only use **pointers**
f = foo_create();
if (!f)
return 1;
// I cannot access the members of `struct foo` here.
// In an opaque API, the struct members are considered
// an implementation detail and cannot be used outside
// of the implementation.
foo_use(f);
foo_destroy(f);
return 0;
}
You have to decide whether you want to hide the details of the structure from the "outside" or not. If you don't want to hide them, just put the structure definition in a.h. Hiding it ensures better decoupling and central control of your b.c over the content, but that means you have to provide a way to create an object in b.c (e.G.
struct A_Structure *create_A_Structure(void);
and use this from the outside.
an unrelated stylistic advice: better don't typedef pointers. While your _Ptr suffix makes it kind of obvious, it's still better to just have the asterisk everywhere because that is what C programmers are used to, so the fact that it's a pointer is obvious at the first glance.
I'd suggest something like this:
/* header */
typedef struct A A;
A *A_create(void);
/* implementation */
struct A
{
int foo;
}
A *A_create(void)
{
return malloc(sizeof(A));
}

How to typecast void pointer based on condition?

To explain more, I have two structures-'first' and 'second' having common variables 'jack' and 'jill'. I want to print jack via a pointer based on if-else condition.
I understand at the time of printing I have to typecast the void pointer. But whether the pointer points to struct a or b is decided on run time.
It is a basic C code. How to overcome this?
Code
#include <stdio.h>
int main(void)
{
typedef struct one
{
int jack;
float jill;
}a;
typedef struct two
{
int jack;
float jill;
char something;
int something1;
}b;
a first;
b second;
void *z;
if(1)
{
a* z;
z = &first;
printf("First one");
}
else
{
b* z;
z = &second;
printf("Second one");
}
printf("%d\n", z->jack);
return 0;
}
Error
prog.c:36:17: warning: dereferencing 'void *' pointer printf("%d\n", z->jack); prog.c:36:17: error: request for member 'jack' in something not a structure or union
You get a compiler warning since the compiler does not understand z->jack since z is a void * (note that the declarations a* z and b* z are not valid outside the scope of the if and else block).
To overcome this you can use a function printJack as shown in the following listing:
#include <stdio.h>
typedef struct one
{
int jack;
float jill;
}a;
typedef struct two
{
int jack;
float jill;
char something;
int something1;
}b;
void printJack(void *pStruct, int type)
{
switch (type)
{
case 1:
printf("jack: %d\n", ((a *)pStruct)->jack);
break;
default:
printf("jack: %d\n", ((b *)pStruct)->jack);
break;
}
}
/*
** main
*/
int main(void)
{
a first;
b second;
void *z;
first.jack = 5;
second.jack = 4892;
printJack(&first, 1);
printJack(&second, 0);
z = &first;
printJack(z, 1);
return (0);
}
I've written code like this often and experienced a lot of trouble with it. Not at the time of implementing, since you are knowing what you are typing at that moment but let's say a few years later if you need to extend your code. You will miss a few places where you cast from void * to a * or b * and you'll spend a lot of time debugging what's going on...
Now I'm writing things like this in the following way:
#include <stdio.h>
typedef struct header
{
int jack;
float jill;
} h;
typedef struct one
{
struct header header;
/* what ever you like */
}a;
typedef struct two
{
struct header header;
char something;
int something1;
/* and even more... */
}b;
void printJack(void *pStruct)
{
printf("jack: %d\n", ((struct header *)pStruct)->jack);
}
/*
** main
*/
int main(void)
{
a first;
b second;
void *z;
first.header.jack = 5;
second.header.jack = 4892;
printJack(&first);
printJack(&second);
v = &first;
printJack(v);
return (0);
}
As you've noticed I have declared a new struct header which covers the the common parts of struct one and struct two. Instead of casting the void * to either a * or b * a "common" cast to struct header * (or h *) is done.
By doing so you can easily extend the "common attribtues" of the structs or you can implement further structs using this header and function printJack still will work. Additionally there is no need for attribute type anymore making is easier to call printJack. You can even change the type of jack without needing to change it in various places within your code.
But remember that struct header needs to be the first element of the structs you use this mechanism. Otherwise you will end up with a few surprises since you are using memory which does not contain the data of the struct header...

Resources