I'm trying to cast a struct inside a struct but am running into issues, heres my simplified code:
#include <stdlib.h>
typedef struct {
void *test;
} abc;
typedef struct {
int a;
int b;
} def;
int main()
{
abc *mystruct = malloc(sizeof(abc) + sizeof(def));
mystruct->(def *)test->a = 3;
return 0;
}
the abc struct may have different types of structs in them, so I'd like to cast dynamically, however, this doesn't appear to work. How do I accomplish this in one statement?
Split the allocation in two parts, first:
abc *mystruct = malloc( sizeof(abc) );
But, when you try to do( if test would be properly cast )
mystruct->test->a
test member isn't pointing anywhere, and by dereferencing it you get undefined behavior.
First point it to valid memory
mystruct->test = malloc( sizeof( def ) ) ;
Then you can use it:
( ( def *)mystruct->test )->a = 3;
^ ^
Notice the parenthesis, you are casting the member void which is mystruct->test not just test.
When casting from void* the proper way is to use static_cast in C++:
abc *mystruct = static_cast<abc*>(malloc(sizeof(abc)));
mystruct->test = malloc(sizeof(def));
static_cast<def*>(mystruct->test)->a = 3;
LIVE DEMO
Now as far as it concerns C. First of, I prefer to define init and finit functions for my structs:
struct abc*
abc_init(int sz) {
struct abc *out = (abc*) malloc(sizeof(abc));
out->test = malloc(sz);
return out;
}
void
abc_finit(struct abc *in) {
if(in) {
if(in->test) free(in->test);
free(in);
}
}
Notice that allocation of struct abc is done in two steps first the memory for struct abc and then for member test.
Now the casting is done like:
((def*)(mystruct->test))->a = 3;
LIVE DEMO
More commonly you would use a union for this sort of thing:
typedef union {
struct {
int a;
int b;
} def;
/* ..other variants you might want */
} abc;
int main() {
abc *mystruct = malloc(sizeof(abc));
mystruct->def.a = 3;
/* do stuff with it */
Try the following
#include <stdlib.h>
#include <stdio.h>
typedef struct {
void *test;
} abc;
typedef struct {
int a;
int b;
} def;
int main()
{
abc *mystruct = malloc( sizeof( abc ) );
if ( mystruct )
{
mystruct->test = malloc( sizeof( def ) );
if ( mystruct->test )
{
( ( def * )mystruct->test )->a = 3;
printf( "%d\n", ( ( def * )mystruct->test )->a );
}
}
if ( mystruct ) free ( mystruct->test );
free( mystruct );
return 0;
}
The output will be
3
(Corrected) ((def *)mystruct->test)->a = 3;
type cast operator has less precedence than -> operator
Here is the reference
Related
I'm trying to make a small library for particle management that allows to "expand" struct with user's data (texture, animation frames, etc). The library would know only the size of the expanded struct.
How do I iterate through the array of unknown struct types but known size of a struct?
typedef struct{
int type;
}Base;
typedef struct{
Base base;
int value;
}inherited;
int main(){
size_t size = sizeof(inherited);
int count = 10;
void *b = malloc(size * count);
for (int i = 0; i < count; i++){
// iterate based on known size & send to callback
callback( &( (size)b )[i] );
}
free(b);
return 0;
}
I assume the code that does the malloc and calls callback doesn't know anything about the type of the object, only its size.
#include <stdlib.h>
void *alloc_and_init(size_t nmemb, size_t size, void (*callback)(void *))
{
void *b = calloc(nmemb, size);
if (b)
{
char *p = b;
for (size_t i = 0; i < nmemb; i++)
{
callback(p);
p += size;
}
}
return b;
}
typedef struct{
int type;
}Base;
typedef struct{
Base base;
int value;
}inherited;
void init_inherited(void *p)
{
inherited *obj = p;
/* do initialization of obj->* here */
}
int main(void)
{
int objcount = 10;
inherited *objarr;
objarr = alloc_and_init(objcount, sizeof(*objarr),
init_inherited);
/* ... */
free(objarr);
}
for( inherited *p = b, *e = p + count; p < e; p++ ){
callback(p);
}
char *b = malloc(size * count);
for (int i = 0; i < count; i++){
// iterate based on known size & send to callback
callback( b + i * size );
}
Polymorphism in C is always rather clunky. Basically you have to construct a "vtable" manually. The naive, simplified version below lets each object have its own function pointer. You'll end up with something rather contrived like this:
#include <stdio.h>
#include <stdlib.h>
typedef struct base_t base_t;
typedef void callback_t (const base_t* arg);
struct base_t
{
int type;
callback_t* callback;
};
typedef struct
{
base_t base;
int value;
} inherited_t;
void callback_base (const base_t* arg)
{
puts(__func__);
}
void callback_inherited (const base_t* arg)
{
const inherited_t* iarg = (const inherited_t*)arg;
printf("%s value: %d\n", __func__, iarg->value);
}
int main (void)
{
// allocate memory
base_t* array [3] =
{
[0] = malloc(sizeof(inherited_t)),
[1] = malloc(sizeof(base_t)),
[2] = malloc(sizeof(inherited_t)),
};
// initialize objects
*(inherited_t*)array[0] = (inherited_t){ .base.callback=callback_inherited, .value = 123 };
*(array[1]) = (base_t){ .callback=callback_base };
*(inherited_t*)array[2] = (inherited_t){ .base.callback=callback_inherited, .value = 456 };
for (int i = 0; i < 3; i++)
{
array[i]->callback(array[i]); // now we get polymorphism here
}
}
A more professional version involves writing a translation unit (.h + .c) per "class" and then combine allocation with initialization in the "constructor". It would be implemented with opaque type, see How to do private encapsulation in C? Inside the constructor, set the vtable corresponding to the type of object allocated.
I'd also boldly claim that any OO solution using void* arguments has some design flaw. The interface should be using the base class pointer. Void pointers are dangerous.
Here is a 2D array of char*, storing for example different strings in different languages :
typedef enum
{
FRENCH,
ENGLISH,
GERMAN,
LANGUAGES_COUNT
} languages_t;
typedef enum
{
HELLO,
THANK_YOU,
WORDS_COUNT
} words_t;
char *text_tab[WORDS_COUNT][LANGUAGES_COUNT] =
{
{"bonjour", "hello", "guten tag"},
{"merci", "thank you", "danke"}
};
No trouble to access it :
int main()
{
printf("%s\n", text_tab[HELLO][ENGLISH]);
printf("%s\n", text_tab[THANK_YOU][FRENCH]);
printf("%s\n", text_tab[HELLO][GERMAN]);
return 0;
}
Now, I don't want to access text_tab directly, but through a structure :
typedef struct
{
int a;
char ***txt; // here is not working
} test_t;
test_t mystruct = {5, text_tab};
The idea is to access text_tab this way :
printf("%s\n", mystruct.txt[BONJOUR][ANGLAIS]);
printf("%s\n", mystruct.txt[MERCI][FRANCAIS]);
printf("%s\n", mystruct.txt[BONJOUR][ALLEMAND]);
How to declare the field "txt" in the structure ?
I only use static allocation and I don't want to copy the content of "text_tab" in "txt", juste use a pointer.
Thanks.
This array
char *text_tab[WORDS_COUNT][LANGUAGES_COUNT] =
{
{"bonjour", "hello", "guten tag"},
{"merci", "thank you", "danke"}
};
has the type char * [WORDS_COUNT][LANGUAGES_COUNT].
So a pointer to elements of the array has the type char * ( * )[LANGUAGES_COUNT]
Hence the structure can be declared like
typedef struct
{
size_t a;
char * ( *txt )[LANGUAGES_COUNT];
} test_t;
And in main you can declare an object of the structure type like
test_t mystruct = { sizeof( text_tab ) / sizeof( *text_tab ), text_tab };
Here is a demonstrative program.
#include <stdio.h>
#define WORDS_COUNT 2
#define LANGUAGES_COUNT 3
typedef struct
{
size_t a;
char * ( *txt )[LANGUAGES_COUNT];
} test_t;
int main(void)
{
char *text_tab[WORDS_COUNT][LANGUAGES_COUNT] =
{
{"bonjour", "hello", "guten tag"},
{"merci", "thank you", "danke"}
};
test_t mystruct = { sizeof( text_tab ) / sizeof( *text_tab ), text_tab };
for ( size_t i = 0; i < mystruct.a; i++ )
{
for ( size_t j = 0; j < sizeof( *mystruct.txt ) / sizeof( **mystruct.txt ); j++ )
{
printf( "%s ", mystruct.txt[i][j] );
}
putchar( '\n' );
}
return 0;
}
The program output is
bonjour hello guten tag
merci thank you danke
Take in mind the following piece of code:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int a;
int b;
int c;
}A;
A *test;
void init(A* a)
{
a->a = 3;
a->b = 2;
a->c = 1;
}
int main()
{
test = malloc(sizeof(A));
init(test);
printf("%d\n", test->a);
return 0;
}
It runs fine! Now imagine that I want to use the malloc function outside the main itself without returning a pointer to the struct. I would put malloc inside init and pass test adress. But this doesnt seem to work.
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int a;
int b;
int c;
}A;
A *test;
void init(A** a)
{
*a = malloc(sizeof(A));
*a->a = 3;
*a->b = 2;
*a->c = 1;
}
int main()
{
init(&test);
printf("%d\n", test->a);
return 0;
}
It keeps telling me that int a(or b/c) is not a member of the struct A when I use the pointer.
Your problem is operator precedence. The -> operator has higher precedence than the * (dereference) operator, so *a->a is read as if it is *(a->a). Change *a->a to (*a)->a:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int a;
int b;
int c;
}A;
A *test;
void init(A** a)
{
*a = malloc(sizeof(A));
(*a)->a = 3;
(*a)->b = 2;
(*a)->c = 1;
}
int main()
{
init(&test);
printf("%d\n", test->a);
return 0;
}
You must add parenthesis:
void init(A **a)
{
*a = malloc(sizeof(A)); // bad you don't verify the return of malloc
(*a)->a = 3;
(*a)->b = 2;
(*a)->c = 1;
}
But it's good practice to do this:
void init(A **a)
{
A *ret = malloc(sizeof *ret); // we want the size that is referenced by ret
if (ret != NULL) { // you should check the return of malloc
ret->a = 3;
ret->b = 2;
ret->c = 1;
}
*a = ret;
}
You need to write (*a)->a = 3; for reasons of precedence.
Even though it's not a direct answer to your question, since we're in the vicinity of initialization I'd like to point out that C11 gives you a nicer syntax to initialize structs:
void init(A **a)
{
A *ret = malloc(sizeof *ret); // we want the size that is referenced by ret
if (ret != NULL) { // you should check the return of malloc
*ret = (A) {3, 2, 1};
// or
*ret = (A) { .a = 3, .b = 2, .c = 1 };
}
*a = ret;
}
Another advantage is that any uninitialized members are zeroed.
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.
For the current project I cannot use C++ (unfortunately), only pure C, and Im having the following problem:
I got 3 distinctive struct that need to call the same function name, and I feel its more elegant the way it is below instead of creating 3 different function for the different type, like I feel its easier to maintain. How can I get the pointer that call the function? Basically what I'm trying to reproduce is basically similar as "this" in C++ or self (in Obj-C), is there anyway I can do that in plain C?
[ test.h ]
enum
{
TYPE_A = 0,
TYPE_B = 1,
TYPE_C = 2
};
typedef struct
{
char type;
void ( *GetType )( void );
// Some other data different than the other struct
}A;
typedef struct
{
char type;
void ( *GetType )( void );
/* Some other data different than the other struct */
}B;
typedef struct
{
char type;
void ( *GetType )( void );
// Some other data different than the other struct
} C;
A *create_a( void );
B *create_b( void );
C *create_c( void );
void GetType( void );
[ test.c ]
A *create_a( void )
{
A *a = ( A * ) calloc( 1, sizeof( A ) );
a->type = TYPE_A;
a->GetType = GetType;
return a;
}
B *create_b( void )
{
B *b = ( B * ) calloc( 1, sizeof( B ) );
b->type = TYPE_B;
b->GetType = GetType;
return b;
}
C *create_c( void )
{
C *c = ( C * ) calloc( 1, sizeof( C ) );
c->type = TYPE_C;
c->GetType = GetType;
return c;
}
void GetType( void )
{
printf("How to get the pointer that call this function to retrieve the type?");
}
[ main.c ]
int main (int argc, const char * argv[])
{
A *a = create_a();
B *b = create_b();
C *c = create_c();
a->GetType();
b->GetType();
c->GetType();
return 0;
}
The traditional way to do this kind of thing (eg in the UNIX kernel) is by using a #define for syntactic sugar:
#define GET_TYPE(X) ((X)->GetType((X)))
Of course if there are more arguments it passes those as well. The function pointers are usually collected in one static "ops" structure which is assigned on creation (instead of every individual function pointer). Each ops vector has a corresponding collection of #defines.
Pass this as a normal parameter (first, to be conventional):
void GetType(void *this);
...
GetType(a); // instead of C++-style a->GetType
It'd be better to have some "base class" (including "int type" field), in this case pointer will be "struct Base *this", not a "void *this").
Personally I always go this way. You can add prefix for a functions of some "class" (for example, Cl1_GetType). This is the way of OO-programming in C. "Real virtual functions" through function pointers could also be used, but it's not such common case.
"this" should be given as a parameter to GetType(). That's how object methods are actually implemented under the hood. Moreover, since GetType should be able to interact with all kind of struct - the structs should have a similar "base class". for example:
#include "stdio.h"
typedef enum
{
TYPE_A = 0,
TYPE_B = 1,
TYPE_C = 2
} my_class_type;
typedef struct
{
char type;
my_class_type ( *GetType )( void* );
}my_base;
my_class_type my_base_GetType( void* my_base_ptr)
{
return ((my_base*)my_base_ptr)->type;
}
typedef struct
{
my_base base;
// Some other data different than the other struct
}A;
typedef struct
{
my_base base;
/* Some other data different than the other struct */
}B;
typedef struct
{
my_base base;
// Some other data different than the other struct
}C;
A *create_a( void )
{
A *a = ( A * ) calloc( 1, sizeof( A ) );
a->base.type = TYPE_A;
a->base.GetType = my_base_GetType;
return a;
}
B *create_b( void )
{
B *b = ( B * ) calloc( 1, sizeof( B ) );
b->base.type = TYPE_B;
b->base.GetType = my_base_GetType;
return b;
}
C *create_c( void )
{
C *c = ( C * ) calloc( 1, sizeof( C ) );
c->base.type = TYPE_C;
c->base.GetType = my_base_GetType;
return c;
}
int main(int argc, char* argv[])
{
A *a = create_a();
B *b = create_b();
C *c = create_c();
printf("%d\n",a->base.GetType(a));
printf("%d\n",b->base.GetType(b));
printf("%d\n",c->base.GetType(c));
return 0;
}
This example implements inheritance and polymorphism. All structs share the same base core and if you want to override GetType() you just change the pointer in base. you can hold a pointer to my_base and dynamically resolve the type.
From what i understood of your question is: "You just want to obtain the value of the type field in the structure in GetType function". Is this right? If yes, you can do it this way:
enum
{
TYPE_A = 0,
TYPE_B = 1,
TYPE_C = 2
};
typedef struct
{
char type;
// Some other data different than the other struct
}A;
typedef struct
{
char type;
/* Some other data different than the other struct */
}B;
typedef struct
{
char type;
// Some other data different than the other struct
} C;
A *create_a( void );
B *create_b( void );
C *create_c( void );
void GetType( void * );
[test.c]
A *create_a( void )
{
A *a = ( A * ) calloc( 1, sizeof( A ) );
a->type = TYPE_A;
return a;
}
B *create_b( void )
{
B *b = ( B * ) calloc( 1, sizeof( B ) );
b->type = TYPE_B;
return b;
}
C *create_c( void )
{
C *c = ( C * ) calloc( 1, sizeof( C ) );
c->type = TYPE_C;
return c;
}
#define GetType(x) (x->type)
[main.c]
int main (int argc, const char * argv[])
{
A *a = create_a();
B *b = create_b();
C *c = create_c();
GetType(a);
GetType(b);
GetType(c);
return 0;
}
Hope this answers your question.