It is possible to do something like this How can I initialize an array of pointers to structs?
but with different structs?
E.g.
static struct structA_t a = {"ads", "as"};
static struct structB_t b = {"zzds", "dfr", "shywsd"};
static struct structC_t c = {"ssa", "ad", "dhksdhs"};
struct some_type *array[] = { &a, &b, &c};
How some_type will look like?
You could define some_type as a union:
typedef union{
struct structA_t;
struct structB_t;
struct structC_t;
}some_type;
This will lead you to the problem that you don't know what's actually contained in which element in the array.
To overcome this, add another field specifying the content that is used:
/* numbers to identify the type of the valid some_type element */
typedef enum my_e_dataId{
dataid_invalid = 0,
dataid_a,
dataid_b,
dataid_c
} my_dataId;
typedef union u_data {
struct structA_t* a;
struct structB_t* b;
struct structC_t* c;
}mydata;
typedef struct s_some_type{
my_dataId dataId;
mydata myData;
}some_type;
Then you could initialize your array as follows:
some_type sta[] = {
{dataid_a, (struct structA_t*) &a},
{dataid_b, (struct structA_t*) &b},
{dataid_c, (struct structA_t*) &c}
};
When you loop over the elements of array, first evaluate dataId so that you know what's contained in myData. Then, for example, access the data of the first element using
sta[0].myData.a->FIELDNAME_OF_A_TO_ACCESS
or the third element with
sta[2].myData.c->FIELDNAME_OF_C_TO_ACCESS
See this ideone for a working example: http://ideone.com/fcjuR
In C this is possible with void pointers (Replace "struct some_type" with "void"), but you really shouldn't be doing this. Arrays are for programming with homogeneous data.
Related
Aim : To create a structure of element having certain properties. Then utilize that structure type by creating it's array in another structure.
struct Element
{
int i;
int j;
int x;
};
struct Sparse
{
int r;
int c;
int n;
struct Element *ele;
ele = (struct Element *)malloc(n*sizeof(struct Element));
};
What I wish to know is that which part of the code am I not allowed to write while creating a structure.
The common way to do this is:
struct Element
{
int i;
int j;
int x;
};
struct Sparse
{
int r;
int c;
int n;
struct Element ele[0]; // Make a zero length array
};
struct Sparse* MakeNewSparse(size_t num_ele)
{
struct Sparse* sparse = malloc(sizeof(*sparse) + num_ele*sizeof(struct Element));
return sparse;
}
This works because accessing off the end of a zero-length array is totally legal in C, provided you have allocated memory there.
In this example, we allocate enough space for the struct Sparse, and then enough more contiguous space for the array of struct Element.
After that, accessing element sparse->ele[5] is totally legal.
The line
ele = (struct Element *)malloc(n*sizeof(struct Element));
should not be part of the struct definition - that's something you do at runtime, along these lines:
struct Sparse s; // create new struct Sparse instance
s.n = get_some_size();
s.ele = malloc( s.n * sizeof *s.ele ); // no need for cast
struct in c is syntactically similar with types like int, char, etc. The definition of a struct is for compiler to know how to use variable declared with that struct such as struct Sparse var;. So the definition of a struct is not actually the code itself. It will be used at compile time.
However, malloc() is a function, which will be used at runtime, so it is nonsense to put malloc() in your struct definition.
The graph adjacency list code in my book is given by:
typedef struct vertexNode //vertexNode in an AdjacencyList
{
VertexType data;
EdgeNodeType *firstEdgeNode;
} VertexNode, AdjList[MAXVEX];
AdjList adjList; # adjList is a MAXVEX-size array
I was confused by the last line in the typedef: typedef struct{...} AdjList[MAXVEX].
The forms I can understand are:
typedef struct{
...
} VertexNode,
VertexNode AdjList[MAXVEX]; # AdjList is a MAXVEX-size array
or
struct{
...
} AdjList[MAXVEX]; # AdjList is a MAXVEX-size array
Grammatically speaking, typedef is actually a storage class, like static or extern, and type alias declarations are read like variable declarations. E.g.
int x;
declares x to be a variable of type int, while
typedef int x;
declares x to be a type alias meaning int.
Similarly,
struct vertexNode {
...
} VertexNode;
would declare VertexNode to be a struct vertexNode variable, but adding typedef makes it an alias for struct vertexNode. Note that struct vertexNode { ... } (the whole thing) is a type, just like int. It first defines struct vertexNode, and then refers to it.
Additionally, array declarations may appear to behave strangely when you use commas:
int x, y[5];
declares x to be an int, while declaring y to be an array of 5 ints. (Functions and pointers are also like this.) There are other questions on this site about it.
Putting everything together, your question looks like this if you take away the typedef:
struct vertexNode
{
VertexType data;
EdgeNodeType *firstEdgeNode;
} VertexNode, AdjList[MAXVEX];
This would declare the type struct vertexNode, the variable VertexNode of type struct vertexNode, and the array AdjList of MAXVEX struct vertexNodes. Adding the typedef means that VertexNode becomes an alias for struct vertexNode and that AdjList becomes an alias for an array of MAXVEX struct vertexNodes. Personally, I wouldn't recommend writing it like this, but I guess it's concise.
This is a sample code.
#include <stdio.h>
typedef char STR[1024];
int main() {
STR a = "1234"; // == char a[1024]
printf( "%s\n", a );
return 0;
}
I wrote a example with data type char.
You can replace it with any class or struct..
so.. Your code..
AdjList a is same with VertexNode a[MAXVEX]
I'm trying to create typedef to function pointer which returns matrix of struct.
I tried:
typedef struct my_struct** (*func)(void)
typedef struct my_struct[4][4] (*func)(void)
but none of them worked.
My matrix of struct is initialized like:
static struct my_struct matrix[4][4];
my code didn't compiled with the 2 options of typedef.
How should I create this typedef?
Thanks.
Arrays cannot be returned. You can however return a pointer to an array. This is what should be returned if you want to retrieve your 2d array from a function.
The function would return a pointer to an array of 4 structs:
struct my_struct (*function(void))[4];
typedef of this type:
typedef struct my_struct (*type(void))[4];
type* p = function;
Arrays cannot be returned from functions.
One can return a pointer to the first element of an array. In your case, the first element of your array is itself an array (a row in a matrix). The syntax needed to declare a pointer to a function returning a pointer to an array is too arcane to be used directly. The most simple, user-friendly way to deal with the situation is to use a typedef .
typedef struct my_struct row[4]; // a 4-element row in a matrix
typedef row* (*func)(void); // pointer-to-function returning pointer-to-row
You cannot omit the size and cannot use a pointer instead of an array, i.e.
typedef struct my_struct row[];
typedef row* (*func)(void); // doesn't do what you want
typedef struct my_struct *row;
typedef row* (*func)(void); // doesn't do what you want
You have to know that returning a pointer into a local array is not allowed in C.
row* myfunc(void)
{
struct my_struct my_matrix[4][4];
return my_matrix; // will compile, but the behaviour is undefined
// a good compiler will warn you
}
You can return a pointer to a static object or to a dynamically allocated object this way.
If you want to return objects and not pointers, you have to use a wrapper struct.
typedef struct { struct my_struct elements[4][4]; } wrapper;
wrapper (*foo)(void); //OK
wrapper myfunc(void)
{
wrapper w;
return w; // OK
}
Is there a way to access individual members of a structure that is nested inside two other structures without using the dot operator multiple times?
Unlike some variants of BASIC or Pascal that have a with keyword which allows you to access inner members of a structure directly, C has no such construct.
You can do this however with pointers. If you have a particular inner member you're going to access frequently, you can store the address of that member in a pointer and access the member through the pointer.
Suppose for example you had the following data structures:
struct inner2 {
int a;
char b;
float c;
};
struct inner1 {
struct inner2 in2;
int flag;
};
struct outer {
struct inner1 in1;
char *name;
};
And a variable of the outer type:
struct outer out;
Instead of accessing the members of the innermost struct like this:
out.in1.in2.a = 1;
out.in1.in2.b = 'x';
out.in1.in2.c = 3.14;
You declare a pointer of type struct inner2 and give it the address of out.in1.in2. Then you can work directly with that.
struct inner2 *in2ptr = &out.in1.in2;
in2ptr->a = 1;
in2ptr->b = 'x';
in2ptr->c = 3.14;
Is there a way to access individual members of a structure that is nested inside two other structures without using the dot operator multiple times?
No. Not via standard C.
To make the accessing code cleaner however, you might consider some static inline helper functions.
For example:
struct snap {
int memb;
};
struct bar {
struct snap sn;
};
struct foo {
struct bar b;
}
static inline int foo_get_memb(const struct foo *f)
{
return f->b.sn.memb;
}
Not completely answering your question.
The 1st member of any struct can be accessed by taking the struct's address, casting it to a pointer type pointing to the struct's 1st member and dereferencing it.
struct Foo
{
int i;
...
};
struct Foo foo = {1};
int i = *((int*) &foo); /* Sets i to 1. */
Adapting this to nested struct's gives us for example:
struct Foo0
{
struct Foo foo;
...
};
struct Foo1
{
struct Foo0 foo0;
...
};
struct Foo2
{
struct Foo1 foo1;
...
};
struct Foo2 foo2;
foo2.foo1.foo0.foo.i = 42;
int i = *((int*) &foo2); /* Initialises i to 42. */
struct Foo0 foo0 = {*((struct Foo*) &foo2)}; /* Initialises foo0 to f002.f001.foo0. */
This is well defined, as the C-Standard guarantees that there is no padding before a struct's 1st member. Still it's not nice.
You could use the -> operator.
You could take the address of an inner member and then access it via the pointer.
i'm looking for creating a function in C language that allows me to receive different structures type as parameters.
For example, if I create 3 different structures
struct a{
struct datatype0{
char test1[10];
}datatype;
struct a *next;
};
struct b{
struct datatype1{
int test1;
char test2[20];
int test3;
}datatype;
struct b *next;
};
struct c{
struct datatype2{
char test1;
char test2;
float test3;
int test4;
int test5;
}datatype;
struct c *next;
};
I wanna create a function that can receives one of theese three different struct as parameter, so I can call only it for initialize first, or second or third kind of structure:
void function("---")//<-- inside the brackets i need to insert a parameter that can be struct a, or struct b or struct c.
{
//here for example I can insert the initialize function that have to work with any struct.
}
I tryed to use a union, but I saw that I have to recreate the initializing function for each kind of struct...I tryed to use void pointers, but i need to cast theese inside the function and I need to create initializing function for each kind of struct too...
Any ideas??
The long and short of it is: avoid to do this whenever possible, but know that you Can pass different structs to a single function if you really have to.
Probably the easiest way is to create a wrapper struct, that contains 2 members: a union, and a flag to let you know which struct is passed.
typedef enum {
A,
B,
C
} struct_type;
struct _wrapper {
union {
struct a A;
struct b B;
struct c C;
};
struct_type flag;
};
void my_function(struct _wrapper *data)
{
switch (data->flag)
{
case A:
struct a val = data.A;
//do stuff with A
break;
case B:
struct b val = data.B;
break;
case C:
struct c val = data.C;
//...
break;
}
}
Another option, although it's considered bad practice, and is something you'll end up regretting is to rely on the fact that the offset of the first member of any struct is guaranteed to be 0. You can cast a pointer to any struct to a pointer to its first member. If the first member of all structs is compatible, you can rely on that (at your own risk).
One way of exploiting this is to set a function pointer as first member, or an enum field that you can use as a flag to identify the struct:
struct a {
void (*common_member)();//
/** other members **/
};
struct b {
void (*common_member)();//needn't be the same name though
/** other members **/
};
Then:
void my_func(void *data)
{//void pointer
((void (*)(void *))data)(data);//cast void *data to function pointer, and pass itself as an argument
}
This can work, if the structs are properly initialized, and the members point to the correct functions, but that's too many if's to rely on really.
Using the enum as first member is slightly less risky, but still not to be recommended. It's a sort of a combination of the function pointer and union approach
void my_func(void *data)
{
//cast void * to struct_type *, dereference AFTER the cast
//because you can't dereference a void *
switch(*((struct_type *) data))
{
case A: /* stuff */ break;
case B: /* struct b */ break;
}
}
All in all, use the first approach. Do not use the function pointer members, and acknowledge the third approach for what it is: true, you don't need a wrapper struct, but it's not that much safer than the original approach (function pointers), and no less verbose than the first approach (with union).
Bottom line: structs and unions are the way to go
In part it works. But for example, if I wanna create a function like:
typedef union elemento{
struct a A;
struct b B;
struct c C;
}elemento;
void inserimentoOrdinato(elemento dausare){
struct b prova;
prova.datatype.test1 = 3;
strcpy(prova.datatype.test2,"TESTA");
prova.datatype.test3 = 200;
prova.next = (struct a*)malloc(sizeof(struct a));
dausare.B = prova;
}
I need to use "dausare.B" or "dausare.C" for the different kinds of structures. It doesn't know itseflt which part of union has to use. Am I rigth? Thank you!
The answer is generic programming and function pointer:
**void * can be a pointer to any struct
Declaration part:
typedef void *Initializer(void* obj);//since every struct has its own fields to initialize
void function(void * obj, Initializer init)
{
init(obj);
}
Usage:
void InitA(void* a_void)
{
struct a* a = (struct a*) a_void;
//init a feilds
a->next = NULL;
}
void InitB(void* b_void)
{
struct b* b = (struct b*) b_void;
//init b feilds
b->next = NULL;
}
void InitC(void* c_void)
{
struct c* c = (struct c*) c_void;
//init a feilds
c->next = NULL;
}
int main()
{
struct a a;
struct b b;
struct c c;
Init(&a,InitA);
Init(&b,InitB);
Init(&c, initC);
return 0;
}
***Keep in mind that you dont have to build a different function for each struct if they have the same fields to initialize.