473,486 Members | 2,114 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Using offsetof() values to access members of a struct

With offsetof() I can get the offset of a member in a struct. AFAICS,
it is portable and clean to use this offset to access that member. I
need to do something like this

struct foo {
struct foo *next;
int a;
int b;
int c;
};

void iterate(struct foo *list, size_t off)
{
struct foo *p;
for (p = list; p; p = p->next) {
int i = *(int *)((char *)p + off); /* [1] */
/* do something with i */
}
}

void func(struct foo *f)
{
iterate(f, offsetof(struct foo, a);
iterate(f, offsetof(struct foo, b);
iterate(f, offsetof(struct foo, c);
}

[1] Is this code portable and without undefined or implementation-defined
behavior?

Or is there a better way to achieve the same?

urs
May 22 '07 #1
6 5906
Urs Thuermann <ur*@isnogud.escape.dewrites:
With offsetof() I can get the offset of a member in a struct. AFAICS,
it is portable and clean to use this offset to access that member. I
need to do something like this

struct foo {
struct foo *next;
int a;
int b;
int c;
};

void iterate(struct foo *list, size_t off)
{
struct foo *p;
for (p = list; p; p = p->next) {
int i = *(int *)((char *)p + off); /* [1] */
/* do something with i */
}
}

void func(struct foo *f)
{
iterate(f, offsetof(struct foo, a);
iterate(f, offsetof(struct foo, b);
iterate(f, offsetof(struct foo, c);
}

[1] Is this code portable and without undefined or implementation-defined
behavior?
I think it is, but I am not one of the most skilled interpreters of
such matters. Stay tuned for more informed voices to come along.
Or is there a better way to achieve the same?
"Better" is a loaded word and the only information we have is that you
want portability. I would at least consider:

int access_a(struct foo *fp) { return fp->a; }
int access_b(struct foo *fp) { return fp->b; }
int access_c(struct foo *fp) { return fp->c; }

void iterate(struct foo *list, int (*access)(struct foo *))
{
struct foo *p;
for (p = list; p; p = p->next) {
int i = access(p);
/* do something with i... */
}
}

void func(struct foo *f)
{
iterate(f, access_a);
iterate(f, access_b);
iterate(f, access_c);
}

--
Ben.
May 22 '07 #2
Urs Thuermann wrote:
With offsetof() I can get the offset of a member in a struct. AFAICS,
it is portable and clean to use this offset to access that member. I
need to do something like this

struct foo {
struct foo *next;
int a;
int b;
int c;
};

void iterate(struct foo *list, size_t off)
{
struct foo *p;
for (p = list; p; p = p->next) {
int i = *(int *)((char *)p + off); /* [1] */
/* do something with i */
}
}

void func(struct foo *f)
{
iterate(f, offsetof(struct foo, a);
iterate(f, offsetof(struct foo, b);
iterate(f, offsetof(struct foo, c);
}

[1] Is this code portable and without undefined or implementation-defined
behavior?
The code at [1] is fine, but the calls to it have too few
parentheses.
Or is there a better way to achieve the same?
In this particular case, yes:

struct foo {
struct foo *next;
int abc[3];
};

.... and work with array indices instead of element offsets.

--
Eric Sosman
es*****@acm-dot-org.invalid
May 22 '07 #3
Urs Thuermann wrote:
With offsetof() I can get the offset of a member in a struct.
Yes.
AFAICS, it is portable
Yes.
and clean
That depends.
to use this offset to access that member. I
need to do something like this

struct foo {
struct foo *next;
int a;
int b;
int c;
};

void iterate(struct foo *list, size_t off)
{
struct foo *p;
for (p = list; p; p = p->next) {
int i = *(int *)((char *)p + off); /* [1] */
/* do something with i */
}
}

void func(struct foo *f)
{
iterate(f, offsetof(struct foo, a);
iterate(f, offsetof(struct foo, b);
iterate(f, offsetof(struct foo, c);
}

[1] Is this code portable and without undefined or implementation-defined
behavior?
Looks like it to me.
Or is there a better way to achieve the same?
Well, the natural and obvious solution is to use an array of
three elements and an index, rather than playing offset games.
That reduces the line

| int i = *(int *)((char *)p + off)

to
int i = p.arrayName[off];

which is, IMAO, twenty-seven times more comprehensible. (Obviously
you call `iterate` with values 0, 1, 2, rather than the offsetof
expressions.)

--
"There's a doorway where there was a wall" /Master Humpries Clock/

Hewlett-Packard Limited registered no:
registered office: Cain Road, Bracknell, Berks RG12 1HN 690597 England

May 22 '07 #4
Eric Sosman <es*****@acm-dot-org.invalidwrites:
The code at [1] is fine, but the calls to it have too few
parentheses.
Ah, yes. The whole example is not anywhere near to my real code, and
was only quickly hacked down for this posting. In my real code,
function names, struct names, and member names and types are
different. The real struct doesn't have three ints but a dozen
pointers to further linked lists which have to be traversed.

Currently, I have a separate iterate() function for each of the struct
members and all have exactly the same structure. I wanted to reduce
code duplication by somwehow passing an argument specifying which
member to work on.
Or is there a better way to achieve the same?

In this particular case, yes:

struct foo {
struct foo *next;
int abc[3];
};

... and work with array indices instead of element offsets.
Good idea. I'll probably convert my dozen of pointers to an array and
define symbolic names for the indices. Thanks for your suggestion.
urs
May 22 '07 #5
Others have answered the specific question; this is more general:

In article <yg*************@janus.isnogud.escape.de>,
Urs Thuermann <ur*@isnogud.escape.dewrote:
>With offsetof() I can get the offset of a member in a struct. AFAICS,
it is portable and clean to use this offset to access that member. ...
A structure member, inside a C compiler, really provides two items:
an offset, and a type. Given those two items -- offset and type --
you can "synthesize" a member-access.

The C syntax "structure.member" essentially means "using the
structure named on the left, which should be an lvalue[%], find
the address of the object implied by that lvalue, add the offset
implied by the member, and access an object whose type is
determined by the member." This rule also works for unions,
where the offset is always zero.

The "offset add" must be done in terms of "bytes" (C bytes, i.e.,
"unsigned char"s), of course. (&structure)+1, using ordinary
(i.e., entire-object-size) pointer arithmetic, points right
past the entire structure, so any nonzero offset would be too
big if this "offset add" were not "de-scaled" down to byte size.

-----
[%] This deliberately ignores the special case of a function return
value of structured type, which has some funny constraints. In
particular, such a return value is the only way to produce an
"array rvalue", which has no address, yet can still be subscripted
to access an array element. If you somehow access the (nonexistent)
address of a struct-type return value or any of its members --
including an array or an array element -- the effect is not defined.
It is generally unwise even to try, whether or not the compiler
catches you. :-)
-----

The C syntax "expr->member" essentially means "using the pointer
value given on the left, and the offset and type implied by
the member, access the object at that offset." This is of course
identical to "(*(expr)).member" since *(expr) produces the lvalue
pointed-to by the expression. Taking its address and adding the
offset has the same effect as just starting with the expression,
treating it as an address, and adding the offset.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
May 24 '07 #6
Chris Torek wrote:
[%] This deliberately ignores the special case of a function return
value of structured type, which has some funny constraints. In
particular, such a return value is the only way to produce an
"array rvalue", which has no address, yet can still be subscripted
to access an array element. If you somehow access the (nonexistent)
address of a struct-type return value or any of its members --
including an array or an array element -- the effect is not defined.
It is generally unwise even to try, whether or not the compiler
catches you. :-)
In C90, an array rvalue cannot be subscripted, and in C99, I don't believe
there is anything prohibiting

struct S { int a[1]; } s;
struct S f(void) { return s; }
int main(void) { int *p; return *(p = f().a); }

(though p may not be dereferenced after the next sequence point).

And function calls are not the only way. The conditional, assignment, and
comma operators can also do it.
May 25 '07 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
6317
by: Hiroki Horiuchi | last post by:
Hello. I wrote a program, but g++ warns a.c:11: warning: invalid access to non-static data member `A::y' of NULL object a.c:11: warning: (perhaps the `offsetof' macro was used incorrectly) ...
9
2934
by: Exits Funnel | last post by:
Consider this code which is a very trimmed down version of some I've inherited and am trying to port from windows to g++: //Begin test1.cpp class foo { int i; int j; }; class bar { bar (int...
6
2176
by: Arthur J. O'Dwyer | last post by:
As far as I know, C89/C90 did not contain the now-standard offsetof() macro. Did C89 mandate that structs had to have a consistent layout? For example, consider the typical layout of the...
10
3358
by: Mark A. Odell | last post by:
Is there a way to obtain the size of a struct element based only upon its offset within the struct? I seem unable to figure out a way to do this (short of comparing every element's offset with...
3
2843
by: Michael B Allen | last post by:
Can offsetof be used to determine the offset of a member within an embedded struct member? For example, let 'struct foo' be a structure with an embedded structure 'struct bar' which has a member...
44
3679
by: Simon Morgan | last post by:
Hi, Can somebody please help me grok the offsetof() macro? I've found an explanation on http://www.embedded.com/shared/printableArticle.jhtml?articleID=18312031 but I'm afraid it still...
13
4994
by: Kantha | last post by:
Hi all, I have declared an Union as follows typedef union { struct interrupt_bits { unsigned char c_int_hs_fs_status : 1, c_setup_intflag : 1,
8
5837
by: Pawel | last post by:
Hallo group members. //p1.cpp #include <stdio.h> #include <linux/stddef.h> struct Person { int m_age; char* m_name; };
24
3453
by: Francine.Neary | last post by:
Just out of personal curiosity :) What do people use offsetof() for? I mean, I can understand why you'd want to be able to take the address of a member of a struct, but you can do that with just...
0
7100
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
1
6842
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
7330
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
1
4865
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4559
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3070
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
1378
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
1
598
muto222
php
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
262
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.