Accessing a member in a nested structure - c

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.

Related

Is it possible to create a function ( in C ), that can operate with different structure?

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.

typedef, structure and type compatibiliy

If I have these two structs:
struct
{
int x;
} A;
struct
{
int x;
} B;
then making A = B; results in a compilation error because the two anonymous structs are not compatible.
However if I do:
typedef struct
{
int x;
} S;
S A;
S B;
A = B; is a legal assignment because they are compatible.
But why? With typedef I understand that the compiler makes this when meet S A and S B:
struct { int x; } A;
struct { int x; } B;
so A and B should not be compatible...
Each anonymous struct declaration is a distinct type; this is why you get a type mismatch when trying to assign one to the other.
A typedef, however, declares an alias (i.e. a new name for something that already exists) for a type (it does not create a new type).
A typedef is also not a simple text replacement, like a preprocessor macro. Your statement
I understand that the compiler make this when meet S A and S B:
struct { int x; } A;
struct { int x; } B;
is where your understanding is wrong.
When you use the type alias S, as in
S A;
S B;
the types of both objects A and B are the same by definition and assigning one to the other is possible.
This is because C treats every untagged struct as a new kind of struct, regardless of the memory layout. However, typedef struct { } name; cannot be used if you want to use the struct in a linked list. You'll need to stick with defining a structure tag in this case, and typedef the tagged struct instead.
struct DistanceInMeter /* Anonymous 1 */
{
int x; /* distance */
};
struct VolumeInCC /* Anonymous 2 */
{
int x; /* volume */
};
struct DistanceInMeter A;
struct VolumeInCC B;
...
A = B; /* Something is wrong here */
Equating different type doesn't always make sense and thus is not allowed.
typedef struct DistanceInMeter /* Anonymous 1 */
{
int x; /* distance */
} Dist_t;
Dist_t C, D;
...
C = D; /* Alright, makes sense */

What is 'forward declaration' and the difference between 'typedef struct X' and 'struct X'?

I am a beginner in C programming and I know the difference between struct type declaration and typedef struct declaration. I came across to know an answer saying that if we define a struct like:
typedef struct {
some members;
} struct_name;
Then it will be like providing an alias to an anonymous struct (as it is not having a tag name). So it can't be used for forward declaration. I don't know what the forward declaration means.
Also, I wanted to know that for the following code:
typedef struct NAME {
some members;
} struct_alias;
Is there any difference between NAME and struct_alias? Or are both equal as
struct_alias is an alias of struct NAME ?
Furthermore, can we declare a variable of type struct NAME like these:
struct_alias variable1;
and/or like:
struct NAME variable2;
or like:
NAME variable3;
struct forward declarations can be useful when you need to have looping struct declarations. Example:
struct a {
struct b * b_pointer;
int c;
};
struct b {
struct a * a_pointer;
void * d;
};
When struct a is declared it doesn't know the specs of struct b yet, but you can forward reference it.
When you typedef an anonymous struct then the compiler won't allow you to use it's name before the typedef.
This is illegal:
struct a {
b * b_pointer;
int c;
};
typedef struct {
struct a * a_pointer;
void * d;
} b;
// struct b was never declared or defined
This though is legal:
struct a {
struct b * b_pointer;
int c;
};
typedef struct b {
struct a * a_pointer;
void * d;
} b;
// struct b is defined and has an alias type called b
So is this:
typedef struct b b;
// the type b referes to a yet undefined type struct b
struct a {
b * struct_b_pointer;
int c;
};
struct b {
struct a * a_pointer;
void * d;
};
And this (only in C, illegal in C++):
typedef int b;
struct a {
struct b * struct_b_pointer;
b b_integer_type;
int c;
};
struct b {
struct a * a_pointer;
void * d;
};
// struct b and b are two different types all together. Note: this is not allowed in C++
Forward declaration is a promise to define something that you make to a compiler at the point where the definition cannot be made. The compiler can use your word to interpret other declarations that it would not be able to interpret otherwise.
A common example is a struct designed to be a node in a linked list: you need to put a pointer to a node into the struct, but the compiler would not let you do it without either a forward declaration or a tag:
// Forward declaration
struct element;
typedef struct {
int value;
// Use of the forward declaration
struct element *next;
} element; // Complete definition
and so it cant be used for forward declaration
I think that author's point was that giving your struct a tag would be equivalent to a forward declaration:
typedef struct element {
int value;
// No need for a forward declaration here
struct element *next;
} element;
Forward declaration is a declaration preceeding an actual definition, usually for the purpose of being able to reference the declared type when the definition is not available. Of course, not everything may be done with the declared-not-defined structure, but in certain context it is possible to use it. Such type is called incomplete, and there are a number of restrictions on its usage. For example:
struct X; // forward declaration
void f(struct X*) { } // usage of the declared, undefined structure
// void f(struct X) { } // ILLEGAL
// struct X x; // ILLEGAL
// int n =sizeof(struct X); // ILLEGAL
// later, or somewhere else altogether
struct X { /* ... */ };
This can be useful e.g. to break circular dependencies, or cut down the compilation time, as the definitions are usually significantly larger, and so more resources are required to parse it.
In your example, struct NAME and struct_alias are indeed equivalent.
struct_alias variable1;
struct NAME variable2;
are correct;
NAME variable3;
is not, as in C the struct keyword is required.
struct_alias and struct NAME are same ,struct_alias is an alias to struct NAME
These both are same and allowed
struct_alias variable1;
struct NAME variable1;
this is illegal
NAME variable3;
See this article on Forward declaration
As others stated before, a forward declaration in C/C++ is the declaration of something with the actual definition unavailable. Its a declaration telling the compiler "there is a data type ABC".
Lets pretend this is a header for some key/value store my_dict.h :
...
struct my_dict_t;
struct my_dict_t* create();
char* get_value(const struct my_dict_t* dict, const char* name);
char* insert(struct my_dict_t* dict, const char* name, char* value);
void destroy(struct my_dict_t* dict);
...
You dont know anything about my_dict_t, but actually, for using the store
you dont need to know:
#include "my_dict.h"
...
struct my_dict_t* dict = create();
if(0 != insert(dict, "AnEntry", strdup("AValue"))) {
...
}
...
The reason for this is: You are only using POINTERS to the data structure.
POINTERS are just numbers, and for dealing with them you dont need to know what they are pointing at.
This will only matter if you try to actually access them, like
struct my_dict_t* dict = create();
printf("%s\n", dict->value); /* Impossible if only a forward decl is available */
So, for implementing the functions, you require an actual definition of my_struct_t.
You might do this in the source file my_dict.c like so:
#include "my_dict.h"
struct my_dict_t {
char* value;
const char* name;
struct my_dict_t* next;
}
struct my_dict_t* create() {
return calloc(1, sizeof(struct my_dict_t));
}
This is handy for several situations, like
For resolving circular type dependencies, like Sergei L. explained.
For encapsulation, like in the example above.
So the question that remains is: Why cant we just omit the forward declaration at all when using the functions above? In the end, it would suffice for the compiler to know that all dict are pointers.
However, the compiler does perform type checks:
It needs to verify that you don't do something like
...
int i = 12;
char* value = get_value(&i, "MyName");
...
It does not need to know how my_dict_t looks like, but it needs to know that &i is not the type of pointer get_value() expects.

Array of pointers to different structs

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.

What is this operator(->) in C? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Arrow operator (->) usage in C
As far as i know only C++ can use classes(obj->something) however i have seen this operator in numerous C applications.
And a small side-question. Usually one uses structures in C like this:
structname.somevariable
However i have seen them used like:
structname.something1.something2
Does it have something to do with the keyword union?
struct A
{
int b;
};
struct A *a;
a->b == (*a).b;
And no, that has nothing to do with unions. It's just getting a member of a member.
if you have a pointer to a struct object, like
struct P * p;
you access members with ->
p->member
if p is not a pointer, you access members with .
struct P p;
p.member
Any C book covers this :P
Operator -> is used to access a member of a struct through a pointer to that structure. The second part of your question is used when accessing nested structures, it is not restricted to the use of unions. For instance:
struct A {
int a;
};
struct B {
struct A baz;
};
int main()
{
struct A foo;
struct B bar;
(&foo)->a = 10;
bar.baz.a = 20;
return 0;
}
C++ classes are an extension of C structs, and an object is just a pointer to a struct. C++ didn't actually invent a whole lot of new stuff; it's called C ++ for a reason.
structs can be nested. Given
struct a {
int a_a;
int a_b;
}
struct b {
int b_a;
struct a b_b;
} a;
you can refer to a.b_b.a_b.
A union uses similar syntax to a struct, but all the members overlap each other. This is useful when you need to interpret a chunk of memory in multiple ways.
I strongly suggest picking up a C book.
x.y.z is used when you want to access a member of a struct that is itself a member of another struct.
typedef struct _POINT
{
int x;
int y;
} POINT;
typedef struct _RECT
{
POINT topLeft;
POINT bottomRight;
} RECT;
int main()
{
RECT r;
r.topLeft.x = 0;
t.topLeft.y = 0;
int width = r.bottomRight.x - r.topLeft.x;
}
I've written a small example in C.
#include <stdio.h>
#include <stdlib.h>
struct a_t {
int a;
/* ... */
};
struct b_t {
struct a_t a;
/* ... */
};
int main()
{
struct a_t a;
struct a_t *b;
b = malloc(sizeof(struct a_t));
a.a = 1;
b->a = 2;
printf("%d; %d;\n", a.a, b->a);
(&a)->a = 3;
(*b).a = 4;
printf("%d; %d;\n", a.a, b->a);
free(b);
struct b_t c;
c.a.a = 5;
printf("%d;\n", c.a.a);
return 0;
}
If I remember correctly, in C++
class IDENTIFIER {
// stuff, possibly including functions
};
is exactly the same as
struct IDENTIFIER {
private:
// stuff, possibly including functions
};
and
struct IDENTIFIER {
// stuff, possibly including functions
};
is exactly the same as
class IDENTIFIER {
public:
// stuff, possibly including functions
};

Resources