?
Solved

Accessing structure members

Posted on 2003-03-08
21
Medium Priority
?
455 Views
Last Modified: 2010-04-15
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
Comment
Question by:arut
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 10
  • 5
  • 4
  • +2
21 Comments
 
LVL 8

Expert Comment

by:akshayxx
ID: 8093729
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
 
LVL 8

Expert Comment

by:akshayxx
ID: 8093776
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
 
LVL 8

Expert Comment

by:akshayxx
ID: 8093806
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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 6

Expert Comment

by:gj62
ID: 8094736
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
 
LVL 6

Expert Comment

by:gj62
ID: 8094741
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
 
LVL 8

Expert Comment

by:akshayxx
ID: 8094878
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
 
LVL 6

Expert Comment

by:gj62
ID: 8095275
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
 
LVL 8

Expert Comment

by:akshayxx
ID: 8095856
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
 
LVL 6

Expert Comment

by:gj62
ID: 8096370
U2!

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

Where's Kdo on this one - he's lurking around somewhere too...
0
 

Author Comment

by:arut
ID: 8101066
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
 
LVL 8

Expert Comment

by:akshayxx
ID: 8101416
>>(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
 

Author Comment

by:arut
ID: 8101780
(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
 
LVL 8

Expert Comment

by:akshayxx
ID: 8102208
>>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
 
LVL 8

Expert Comment

by:akshayxx
ID: 8102215
>>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
 
LVL 8

Expert Comment

by:akshayxx
ID: 8102230
>>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
 
LVL 8

Expert Comment

by:akshayxx
ID: 8102235
its not me .. my internet sucked .. three times it led me to 'blank page'
0
 

Author Comment

by:arut
ID: 8104657
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
 
LVL 6

Expert Comment

by:gj62
ID: 8104724
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
 
LVL 20

Expert Comment

by:jmcg
ID: 10089603
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
 

Author Comment

by:arut
ID: 10110211
Hi gj62,

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

Thanks,
Arut

0
 

Accepted Solution

by:
modulo earned 0 total points
ID: 10136187
PAQed, with points refunded (125)

modulo
Community Support Moderator
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Have you thought about creating an iPhone application (app), but didn't even know where to get started? Here's how: ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Important pre-programming comments: I’ve never tri…
Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use switch statements in the C programming language.

765 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question