Is it preferable to dynamically allocate the 'inner' structs in a nested hierarchy? If the parent struct is dynamically allocated, does it even matter? Why/how does it matter? Just trying to build my understanding of implications of different, seemingly contradictory, ways memory is dealt with in a code base I'm dealing with.
For example, what are the benefits of:
struct Foo_type {
int i;
}; typedef struct Foo_type Foo;
struct Bar_type {
Foo f;
}; typedef struct Bar_type Bar;
int main() {
Bar* b = malloc(sizeof(Bar));
/* yada yada yada */
free(b);
return 0;
}
As opposed to:
struct Foo_type {
int i;
}; typedef struct Foo_type Foo;
struct Bar_type {
Foo* f;
}; typedef struct Bar_type Bar;
int main() {
Bar* b = malloc(sizeof(Bar));
b->f = malloc(sizeof(Foo));
/* yada yada yada */
free(b->f);
free(b);
return 0;
}
Are they equivalent/different?
As an added to #AndersK. answer, the first method (non dynamic) is preferred when we want to emulate inheritance, declaring the base struct inside the derived struct and casting the derived as base:
#include <stdio.h>
#include <stdlib.h>
struct foo {
int i;
};
struct bar {
struct foo f;
};
static void func(struct foo *f, int i)
{
f->i = i;
}
int main(void)
{
struct bar *b = malloc(sizeof(*b));
func((struct foo *)b, 1);
printf("%d\n", b->f.i);
return 0;
}
In case one, the struct is contained in one memory allocation block, so you can memcpy it and need only one free for freeing it.
In case two you occupy two memory blocks not necessarily beside each other so you will have additional hassle of keeping track of those two blocks.
If you start having more pointers and members in Bar_type you will increase the complexity of copying an instance of the type.
Related
typedef struct foo_s {
int a;
} foo;
typedef struct bar_s {
foo;
int b;
} bar;
Essentially I want to do:
bar b;
b.a;
I know that i could do b.foo_name.a if I had named the foo struct in bar, but Id prefer not to.
Any way to do this?
This question has gotten a variety of different answers, so let me explain the need. The reason I want to do this is because I have a library which I need to adapt to my situation, meaning that I cant modify the original struct decleration. Furthermore, all I need to do is add 1 item to the beginning of the struct (why the beginning? because I have an 'object' struct which heads all the structs in the project). I could simply embed the struct like you mention but its REALLY annoying as all references will need to be typed 'variable->image.location' that 'image.' typed a billion types is really annoying.
Evidently this feature has been added to C11, but alas I don't have access to a C compiler of recent vintage (>= GCC 4.6.2).
typedef struct foo {
int a;
} foo;
typedef struct bar {
struct foo;
int b;
} bar;
int main() {
bar b;
b.a = 42;
b.b = 99;
return 0;
}
You can, using pointers, because a pointer to a structure object is guaranteed to point its first member. See e.g. this article.
#include <stdlib.h>
#include <stdio.h>
typedef struct foo_s {
int a;
} foo;
typedef struct bar_s {
foo super;
int b;
} bar;
int fooGetA(foo *x) {
return x->a;
}
void fooSetA(foo *x, int a) {
x->a = a;
}
int main() {
bar* derived = (bar*) calloc(1, sizeof(bar));
fooSetA((foo*) derived, 5);
derived->b = 3;
printf("result: %d\n", fooGetA((foo*) derived));
return 0;
}
Not possible in C the way you did. But you can mimic inheritance having a foo member variable in bar.
typedef struct bar_s {
foo obj;
int b;
} bar;
bar b;
b.obj.a = 10;
If you ment
typedef struct foo_s {
int a;
} foo;
typedef struct bar_s {
foo my_foo;
int b;
} bar;
so you can do:
bar b; b.my_foo.a = 3;
Otherwise, There's no way of doing it in C since the sizeof(bar_s) is detriment on compile time. It's not a good practice but you can save a void * ptr; pointer within bar_s, and another enum which describes the ptr type, and cast by the type.
i.e:
typedef enum internalType{
INTERNAL_TYPE_FOO = 0,
}internalType_t;
typedef struct bar_s {
internalType_t ptrType;
void* ptr;
int b;
} bar;
and then:
bar b; foo f;
b.ptrType = INTERNAL_TYPE_FOO;
b.ptr = &f;
and some where else in the code:
if (b.ptrType == INTERNAL_TYPE_FOO) {
foo* myFooPtr = (foo *)b.ptr;
}
It can be easily done via preprocessor:
Create a file named base_foo.h:
int foo;
Then simply include it:
typedef struct foo_s {
#include "base_foo.h"
} foo;
typedef struct bar_s {
#include "base_foo.h"
int b;
} bar;
There is a confusion between anonymous structures and unions with nameless field. The nameless field is a Microsoft Extension.
struct known {
struct /* anonymous */ {
int anonymous;
};
int known;
};
An anonymous struct or union is a struct or union without any tag name that is embedded within another struct or union. It does not need to have any field names either.
A nameless field is a Microsoft Extension that allows limited inheritance in C.
struct A {
int a;
};
struct B {
struct A: // nameless field
int b;
};
Anonymous struct or union are not Nameless Fields, and Nameless Fields are not Anonymous, at least the way C11 standard defines it.
You can try using inheritance:
struct foo_s
{
int a;
};
struct bar_s: foo_a
{
int b;
};
Works in C++, not sure if it works in C.
This is the simplest way without the c flags
#include <stdio.h>
#define foo_s struct { int a; }
typedef foo_s foo;
typedef struct bar_s {
foo_s; // extends foo_s
int b;
} bar;
int main(void)
{
bar b = {
.a = 1,
.b = 2,
};
foo *f = (foo *)&b;
printf("a: %d\n", f->a);
return 0;
}
$ gcc inherit.c
$ ./a.out
a: 1
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;}
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 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;
}
typedef struct foo_s {
int a;
} foo;
typedef struct bar_s {
foo;
int b;
} bar;
Essentially I want to do:
bar b;
b.a;
I know that i could do b.foo_name.a if I had named the foo struct in bar, but Id prefer not to.
Any way to do this?
This question has gotten a variety of different answers, so let me explain the need. The reason I want to do this is because I have a library which I need to adapt to my situation, meaning that I cant modify the original struct decleration. Furthermore, all I need to do is add 1 item to the beginning of the struct (why the beginning? because I have an 'object' struct which heads all the structs in the project). I could simply embed the struct like you mention but its REALLY annoying as all references will need to be typed 'variable->image.location' that 'image.' typed a billion types is really annoying.
Evidently this feature has been added to C11, but alas I don't have access to a C compiler of recent vintage (>= GCC 4.6.2).
typedef struct foo {
int a;
} foo;
typedef struct bar {
struct foo;
int b;
} bar;
int main() {
bar b;
b.a = 42;
b.b = 99;
return 0;
}
You can, using pointers, because a pointer to a structure object is guaranteed to point its first member. See e.g. this article.
#include <stdlib.h>
#include <stdio.h>
typedef struct foo_s {
int a;
} foo;
typedef struct bar_s {
foo super;
int b;
} bar;
int fooGetA(foo *x) {
return x->a;
}
void fooSetA(foo *x, int a) {
x->a = a;
}
int main() {
bar* derived = (bar*) calloc(1, sizeof(bar));
fooSetA((foo*) derived, 5);
derived->b = 3;
printf("result: %d\n", fooGetA((foo*) derived));
return 0;
}
Not possible in C the way you did. But you can mimic inheritance having a foo member variable in bar.
typedef struct bar_s {
foo obj;
int b;
} bar;
bar b;
b.obj.a = 10;
If you ment
typedef struct foo_s {
int a;
} foo;
typedef struct bar_s {
foo my_foo;
int b;
} bar;
so you can do:
bar b; b.my_foo.a = 3;
Otherwise, There's no way of doing it in C since the sizeof(bar_s) is detriment on compile time. It's not a good practice but you can save a void * ptr; pointer within bar_s, and another enum which describes the ptr type, and cast by the type.
i.e:
typedef enum internalType{
INTERNAL_TYPE_FOO = 0,
}internalType_t;
typedef struct bar_s {
internalType_t ptrType;
void* ptr;
int b;
} bar;
and then:
bar b; foo f;
b.ptrType = INTERNAL_TYPE_FOO;
b.ptr = &f;
and some where else in the code:
if (b.ptrType == INTERNAL_TYPE_FOO) {
foo* myFooPtr = (foo *)b.ptr;
}
It can be easily done via preprocessor:
Create a file named base_foo.h:
int foo;
Then simply include it:
typedef struct foo_s {
#include "base_foo.h"
} foo;
typedef struct bar_s {
#include "base_foo.h"
int b;
} bar;
There is a confusion between anonymous structures and unions with nameless field. The nameless field is a Microsoft Extension.
struct known {
struct /* anonymous */ {
int anonymous;
};
int known;
};
An anonymous struct or union is a struct or union without any tag name that is embedded within another struct or union. It does not need to have any field names either.
A nameless field is a Microsoft Extension that allows limited inheritance in C.
struct A {
int a;
};
struct B {
struct A: // nameless field
int b;
};
Anonymous struct or union are not Nameless Fields, and Nameless Fields are not Anonymous, at least the way C11 standard defines it.
You can try using inheritance:
struct foo_s
{
int a;
};
struct bar_s: foo_a
{
int b;
};
Works in C++, not sure if it works in C.
This is the simplest way without the c flags
#include <stdio.h>
#define foo_s struct { int a; }
typedef foo_s foo;
typedef struct bar_s {
foo_s; // extends foo_s
int b;
} bar;
int main(void)
{
bar b = {
.a = 1,
.b = 2,
};
foo *f = (foo *)&b;
printf("a: %d\n", f->a);
return 0;
}
$ gcc inherit.c
$ ./a.out
a: 1