Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 456
  • Last Modified:

Accessing structure members

I came across the following:

#define FIELDOFFSET(type,member) ( (size_t) &(((type*) 0)->member) )

I was amazed that the above can actually access individual members of a structure,
but, couldn't understand the syntax though.

How is it possible to access a structure member just by a typecast of zero?
Is there some general rule that I am missing?


Regards,
Arut
0
arut
Asked:
arut
  • 10
  • 5
  • 4
  • +2
1 Solution
 
akshayxxCommented:
this doesnt access the particular member in a struct..
rather it gives you the number of bytes of offset that the particular member is located .. with respect to the address to which any variable of type ( struct st ) will point to in the memory..

like this

#include <stdio.h>
#define FIELDOFFSET(type,member) ( (size_t) &(((type*) 0)->member) )

typedef struct __{
char x;
float z;
int y;
char i;
int e;
}st;

main(){
int p;

p=FIELDOFFSET(st,x);
printf("%d\n",p);

p=FIELDOFFSET(st,z);
printf("%d\n",p);

p=FIELDOFFSET(st,y);
printf("%d\n",p);

p=FIELDOFFSET(st,e);
printf("%d\n",p);

}
0
 
akshayxxCommented:
forgot to show the output of the above piece of code

0
4
8
16

SO in my example for the struct of type
struct st
members  x,z,y,e are located at
0,4,8,16 bytes respectively  w.r.t to pointer to struct


so if u declare a variable of type
st *ptr;
and do
ptr=(st*)malloc(sizeof(st));

then in memory relative positions of members can be calculated with above FIELDOFFSET macro
0
 
akshayxxCommented:
forgot one more thing ...using above macro FIELDOFFSET..
its not very straight forward to access the 'member'

like for my example if i have
st* ptr;
ptr=(st*)malloc(sizeof(st));

and ptr->e=1234;

and u have
int e;

then to get the value of 'e'  u'll have to do

e= *((int*)((void*)ptr+FIELDOFFSET(st,e)));

which definitely is pretty twisted statement.. then to straight away use ptr->e;

by the way u havent told us that whereever u came across that macro .. how r they using it .. show that too,
so that we can explain its usage
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
gj62Commented:
The macro is right out of the C FAQ, which also explains that it is not always portable (but that ANSI compilers *should* have an offsetof() macro defined for that particular system.  In other words, if you can use offsetof(), you are MUCH better off because it should be supported on any ANSI system.

From the FAQ:

ANSI C defines the offsetof() macro, which should be used if available; see <stddef.h>. If you don't have it, one possible implementation is

     #define offsetof(type, mem) ((size_t) \
          ((char *)&((type *)0)->mem - (char *)(type *)0))


This implementation is not 100% portable; some compilers may legitimately refuse to accept it.

The only time I could think you would want to use it is if you wanted to access structure fields by name at runtime, e.g.

Build a table of names and offsets, using the offsetof() macro. The offset of field b in struct a is

     offsetb = offsetof(struct a, b)


If structp is a pointer to an instance of this structure, and field b is an int (with offset as computed above), b's value can be set indirectly with

     *(int *)((char *)structp + offsetb) = value;
0
 
gj62Commented:
BTW - you need to do this, rather than just calculating it for yourself based upon the size of the other members in the struct, because of internal structure padding, etc.  C makes no guarantees about that until compile time...
0
 
akshayxxCommented:
gj62 :
>>>*(int *)((char *)structp + offsetb) = value;

it looks pretty similar to what i posted,

e= *((int*)((void*)ptr+FIELDOFFSET(st,e)));

 its just that,i used the expression on the other side
my turn for <grin>
 
0
 
gj62Commented:
akshayxx -

You're right - I was just trying to show what the FAQ said about being "ANSI standard" - and that is that ANSI offsetof() macro and yours are basically the same.  However, for portability, you should use (or at least name it) offsetof, so that on the systems on which it is NOT portable, hopefully the compiler already has a macro...

In other words, the code should check if offsetof is already defined, and if not, then you can try that one - but whether it works or not is system dependent...
0
 
akshayxxCommented:
gj62:
yes i understand..i just didnt want to loose this chance of my <grin>.. cause  i think you are one of those better experts on this site , which  i find good enough to learn from.
0
 
gj62Commented:
U2!

Of course, this is what we do on the weekends...!

Where's Kdo on this one - he's lurking around somewhere too...
0
 
arutAuthor Commented:
Thanks everybody, but I still have a question!

I didn't understand the expr, (type*) 0)->member).

How is it possible to get offset w.r.t
to the starting address of the structure by just typecasting to 0 ??

Please explain.

Regards,
Arut
0
 
akshayxxCommented:
>>(type*) 0)

this statement means not much ..
it means assume a memory location whose address is 0..
start reading from that location as if it held a structure of type 'type'

so if u try to access member 'member' of struct of type 'type'

and take the address .. then it will give u the address  with respect to address '0'..

if u do this

typedef struct _st{
int x;
int y;
}st;

st st1;
then u can get offset like this also

offset of y=  &(st1.y) -&(st1);


0
 
arutAuthor Commented:
(type*) 0)

Somehow the above expr seems strange to me!

Can the above expression be done for an array.

For example assume that the the starting address of the array is at 0 and access the 3 element for example!!
0
 
akshayxxCommented:
>>Can the above expression be done for an array.
what exactly do u mean by this ..
btw if u have array
int x[10];

to access the 3rd element ( a[2] ) .. i have shown 3 methods..

#include <stdio.h>
main () {
int a[10];

a[2]=25;
printf("%d\n",a[2]);

*(a+2)=45;
printf("%d\n",a[2]);

//this is some what close on the lines of ur question
*((int*)((void*)a+2*sizeof(int)))=55;
printf("%d\n",a[2]);

}
0
 
akshayxxCommented:
>>Can the above expression be done for an array.
what exactly do u mean by this ..
btw if u have array
int x[10];

to access the 3rd element ( a[2] ) .. i have shown 3 methods..

#include <stdio.h>
main () {
int a[10];

a[2]=25;
printf("%d\n",a[2]);

*(a+2)=45;
printf("%d\n",a[2]);

//this is some what close on the lines of ur question
*((int*)((void*)a+2*sizeof(int)))=55;
printf("%d\n",a[2]);

}
0
 
akshayxxCommented:
>>Can the above expression be done for an array.
what exactly do u mean by this ..
btw if u have array
int x[10];

to access the 3rd element ( a[2] ) .. i have shown 3 methods..

#include <stdio.h>
main () {
int a[10];

a[2]=25;
printf("%d\n",a[2]);

*(a+2)=45;
printf("%d\n",a[2]);

//this is some what close on the lines of ur question
*((int*)((void*)a+2*sizeof(int)))=55;
printf("%d\n",a[2]);

}
0
 
akshayxxCommented:
its not me .. my internet sucked .. three times it led me to 'blank page'
0
 
arutAuthor Commented:
akshayxx,

I guess I didn't convey my thoughts appropriately.

The point I was trying to make is if it is possible to assume for a structure that its starting memory location is 0 why not for an array?

Can't we have something like p = ((int *)&((type *)0)

where int *p and to get the offset of third element do
*(p+2). Basically I am not able to digest the thought of
assuming the starting address of a structure to be 0 and
find the offsets. In that case would the following also produce the same result for a structure:

#define FIELDOFFSET(type,member) ((size_t)&(((type*) 1)->member) )







0
 
gj62Commented:
The reason you have to do it this way is because C will pad structures, both internally, and externally (though external doesn't matter on the member offset).

The element offset of an array is always

offset=sizeof(type)*array_element;
0
 
jmcgOwnerCommented:
Nothing has happened on this question in more than 10 months. It's time for cleanup!

My recommendation, which I will post in the Cleanup topic area, is to
split points [grade B] between akshayxx [75 pts] and gj62 [50 pts] (rather confusing as a PAQ, question about 0 not fully answered).

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

jmcg
EE Cleanup Volunteer
0
 
arutAuthor Commented:
Hi gj62,

Sorry for the delay :(
Please give some idea on what internal/external padding is about!

Thanks,
Arut

0
 
moduloCommented:
PAQed, with points refunded (125)

modulo
Community Support Moderator
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 10
  • 5
  • 4
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now