469,128 Members | 1,655 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,128 developers. It's quick & easy.

Mechanics of calculating structure-member offsets

What are the mechanics involved in the calculation of an offset of a
structure member, demonstrated in this piece of code?

#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

Suppose you have struct foobar and want to compute the offset of
element boo, this is how it is done:

(unsigned long)(&((struct foobar *)0)->boo)

What does memory address 0 refer to?

cman

Mar 2 '07 #1
9 5048
On Mar 2, 12:34 pm, "cman" <til...@gmail.comwrote:
What are the mechanics involved in the calculation of an offset of a
structure member, demonstrated in this piece of code?

#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

Suppose you have struct foobar and want to compute the offset of
element boo, this is how it is done:

(unsigned long)(&((struct foobar *)0)->boo)

What does memory address 0 refer to?
The right way to get byte offsets in structs is to use the offsetof()
macro.
>From the C-FAQ:
2.14: How can I determine the byte offset of a field within a
structure?

A: 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.

See question 2.15 below for a usage hint.

References: ISO Sec. 7.1.6; Rationale Sec. 3.5.4.2; H&S
Sec. 11.1 pp. 292-3.

If you want to understand how it works, then just run it through the
preprocessor of your compiler and it will immediately become obvious
what is going on.
P.S.
Don't use this custom one unless your broken compiler does not provide
the real thing.

Mar 2 '07 #2
In article <11**********************@n33g2000cwc.googlegroups .com>,
cman <ti****@gmail.comwrote:
>What are the mechanics involved in the calculation of an offset of a
structure member, demonstrated in this piece of code?
>#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
Dubious ones. C semantics are such that even referring to an
invalid pointer is not allowed (except to compare it to a
null pointer constant), so the above is non portable even though
the memory at location 0 (or just a little thereafter) is not
actually referenced.

It is, though, legal for an implementation to use this kind of
grunge in the implementation headers, as implementation headers
may make use of implementation behaviour that mere mortals ought not
to deal with.

>Suppose you have struct foobar and want to compute the offset of
element boo, this is how it is done:
>(unsigned long)(&((struct foobar *)0)->boo)
>What does memory address 0 refer to?
It's just a 0, converted to an address. Structures are laid out
in increasing address order, so if you know the address of a
structure member and subtract the address of the first element
of the structure, you get the offset of the member into the structure.
But if the structure address has been set as 0, you are subtracting
off 0, which of course doesn't take any extra steps to do, making
the expression simpler.

This requires reliance on behaviour left unspecified in the standard.
Do not use this trick yourself in any program you wish to
be portable.
--
Okay, buzzwords only. Two syllables, tops. -- Laurie Anderson
Mar 2 '07 #3
"user923005" <dc*****@connx.comwrites:
[...]
The right way to get byte offsets in structs is to use the offsetof()
macro.
>>From the C-FAQ:

2.14: How can I determine the byte offset of a field within a
structure?
[snip]
If you want to understand how it works, then just run it through the
preprocessor of your compiler and it will immediately become obvious
what is going on.
P.S.
Don't use this custom one unless your broken compiler does not provide
the real thing.
And if your implementation doesn't provide offsetof() (it's defined in
<stddef.h>), find a different one. The standard requires offsetof()
to exist; if it doesn't, your implementation is *badly* broken, and
anything else in the language could be missing or broken.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Mar 2 '07 #4
cman wrote:
What are the mechanics involved in the calculation of an offset of a
structure member, demonstrated in this piece of code?

#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
#define list_entry(type,member) offsetof(type,member)
>
Suppose you have struct foobar and want to compute the offset of
element boo, this is how it is done:

(unsigned long)(&((struct foobar *)0)->boo)
No, it's not. This is how it is done:
offsetof(struct foobar, boo);
Mar 2 '07 #5
On 2007-03-02 22:08:47 +0100, Keith Thompson <ks***@mib.orgsaid:
And if your implementation doesn't provide offsetof() (it's defined in
<stddef.h>), find a different one. The standard requires offsetof()
to exist; if it doesn't, your implementation is *badly* broken, and
anything else in the language could be missing or broken.

Just a curiosity: is offsetof() required by the standard to be a
#define? Can I check against it by simply using the following code?

#ifndef offsetof
#error .........
#endif

--
Sensei <senseiwa at Apple's mac dot com>

We know Linux is the best, it can do infinite loops in five seconds.
(Linus Torvalds)

Mar 3 '07 #6

Sensei wrote:
On 2007-03-02 22:08:47 +0100, Keith Thompson <ks***@mib.orgsaid:
And if your implementation doesn't provide offsetof() (it's defined in
<stddef.h>), find a different one. The standard requires offsetof()
to exist; if it doesn't, your implementation is *badly* broken, and
anything else in the language could be missing or broken.


Just a curiosity: is offsetof() required by the standard to be a
#define?
As far as I can tell, yes.
Can I check against it by simply using the following code?

#ifndef offsetof
#error .........
#endif
Presumably, you can.

Mar 3 '07 #7
santosh wrote, On 03/03/07 08:51:
Sensei wrote:
>On 2007-03-02 22:08:47 +0100, Keith Thompson <ks***@mib.orgsaid:
>>And if your implementation doesn't provide offsetof() (it's defined in
<stddef.h>), find a different one. The standard requires offsetof()
to exist; if it doesn't, your implementation is *badly* broken, and
anything else in the language could be missing or broken.

Just a curiosity: is offsetof() required by the standard to be a
#define?

As far as I can tell, yes.
>Can I check against it by simply using the following code?

#ifndef offsetof
#error .........
#endif

Presumably, you can.
Although I can't see why you would want to seeing as it has been
required as part of the C standard since 1989.
--
Flash Gordon
Mar 3 '07 #8
Sensei <senseiwa at Apple's mac dot comwrites:
On 2007-03-02 22:08:47 +0100, Keith Thompson <ks***@mib.orgsaid:
>And if your implementation doesn't provide offsetof() (it's defined in
<stddef.h>), find a different one. The standard requires offsetof()
to exist; if it doesn't, your implementation is *badly* broken, and
anything else in the language could be missing or broken.

Just a curiosity: is offsetof() required by the standard to be a
#define?
Yes.
Can I check against it by simply using the following code?

#ifndef offsetof
#error .........
#endif
Well, probably. In a conforming implementation, that will just tell
you whether you've #include'd <stddef.h(and not explicitly undefined
offsetof afterward). In a non-conforming implementation, how do you
know that #ifndef is going to work properly?

It's possible to have a working compiler and a broken <stddef.h>, but
I really don't think there's much point in testing for it (unless
you're writing a conformance test suite). If you need offsetof(),
just go ahead and use it; if it's not defined, you'll get an error
message. (The compiler won't treat it as a call to an external
function because the first argument is a type name.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Mar 3 '07 #9
santosh wrote:
Sensei wrote:
>On 2007-03-02 22:08:47 +0100, Keith Thompson <ks***@mib.orgsaid:
>>And if your implementation doesn't provide offsetof() (it's defined in
<stddef.h>), find a different one. The standard requires offsetof()
to exist; if it doesn't, your implementation is *badly* broken, and
anything else in the language could be missing or broken.

Just a curiosity: is offsetof() required by the standard to be a
#define?

As far as I can tell, yes.
>Can I check against it by simply using the following code?

#ifndef offsetof
#error .........
#endif

Presumably, you can.
However that is a silly thing to do. Just #include <stddef.hand
you KNOW it is available. If you don't include stddef.h you KNOW
it is not available (it is not allowable to #define things
available in the standard headers).

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
Mar 3 '07 #10

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

9 posts views Thread by Abby Lee | last post: by
12 posts views Thread by Anthony Robinson | last post: by
1 post views Thread by StormyTheCat | last post: by
13 posts views Thread by racygirl | last post: by
reply views Thread by zhoujie | last post: by
reply views Thread by Mortomer39 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.