[comp.lang.c] finding offset of a member in C structures

pckim@unisql.UUCP (Pyung-Chul Kim) (05/18/91)

I have a question about finding offset of a member in a structure of C.
For example, in the following structure, `a_struct',

	struct a_struct {
		short	member1;
		char	member2;
		int	memner3;
	};

can I get the offset of member2 at *compiling time* and *portably* ?
The offset may be different for machines and compilers because
they employ different member alignment schemes.
I think there is no reason for C compiler not to provide such facility.
It is possible to provide a compiler operator:
	offsetof(member_name,structure_type_name)
as it provides 'sizeof' operator.
Do you know if there is a compiler operator like above, or is there any
alternative solution.

Thanks in advance.

P.S.
we can get the offset at run_time like following:
#define offsetof(a,b)	((int)&((b *)0->a))
But, what I mean is *at compile time*.

-- 
Pyung-Chul Kim

UniSQL, Inc.
9390 Research Blvd., Kaleido II, Suite 220, Austin, TX 78759
Internet: execu!sequoia!unisql!pckim@cs.utexas.edu
UUCP: {uunet, cs.utexas.edu!execu}!sequoia!unisql!pckim
TEL: (512)343-7297 Ext. 332
FAX: (512)343-7383

gwyn@smoke.brl.mil (Doug Gwyn) (05/20/91)

In article <1276@unisql.UUCP> pckim@unisql.UUCP (Pyung-Chul Kim) writes:
-	struct a_struct {
-		short	member1;
-		char	member2;
-		int	memner3;
-	};
-can I get the offset of member2 at *compiling time* and *portably* ?

Yes, but you shouldn't very often need to do so.

-It is possible to provide a compiler operator:
-	offsetof(member_name,structure_type_name)
-as it provides 'sizeof' operator.
-Do you know if there is a compiler operator like above, or is there any
-alternative solution.

Standard C provides an offsetof() macro, but you don't really need one.
	struct a_struct foo;
	int offset2 = (char *)&foo.member2 - (char *)&foo; /* for example */

shankar@hpcupt3.cup.hp.com (Shankar Unni) (05/20/91)

In comp.lang.c, pckim@unisql.UUCP (Pyung-Chul Kim) writes:

> I have a question about finding offset of a member in a structure of C.
> For example, in the following structure, `a_struct',

Why don't you invest $25 or so in a *recent* C textbook (Kernighan and
Ritchie's 2nd Edition book is an excellent choice)? You'll find your
question answered there (look under the index for "offsetof").
-----
Shankar Unni                                   E-Mail:
HP India Software Operation, Bangalore       Internet: shankar@india.hp.com
Phone : +91-812-261254 x417                      UUCP: ...!hplabs!hpda!shankar

osbornk@mist.CS.ORST.EDU (Kasey S. Osborn) (05/21/91)

In article <16194@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
|In article <1276@unisql.UUCP> pckim@unisql.UUCP (Pyung-Chul Kim) writes:
|-struct a_struct {
|-short	member1;
|-char  member2;
|-int   member3;
|-};
|-can I get the offset of member2 at *compiling time* and *portably* ?
|
|Yes, but you shouldn't very often need to do so.
|
|-It is possible to provide a compiler operator:
|-	offsetof(member_name,structure_type_name)
|-as it provides 'sizeof' operator.
|-Do you know if there is a compiler operator like above, or is there any
|-alternative solution.
|
|Standard C provides an offsetof() macro, but you don't really need one.
|	struct a_struct foo;
|	int offset2 = (char *)&foo.member2 - (char *)&foo; /* for example */

Really?  I can't find a reference to offsetof() in any of my C references.
In fact, GNU CC does not preprocess offsetof() and instead treats it as an
external reference.  Are you sure this is standard?

What compiler are you using?  What is the syntax of offsetof()?  I've
been trying to find a palatable solution to this problem with no luck.

kaleb@thyme.jpl.nasa.gov (Kaleb Keithley) (05/21/91)

In article <16194@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
>In article <1276@unisql.UUCP> pckim@unisql.UUCP (Pyung-Chul Kim) writes:
>-	struct a_struct {
>-		short	member1;
>-		char	member2;
>-		int	memner3;
>-	};
>-can I get the offset of member2 at *compiling time* and *portably* ?
>
>Yes, but you shouldn't very often need to do so.

Opinion or Fact?

>-It is possible to provide a compiler operator:
>-	offsetof(member_name,structure_type_name)
>-as it provides 'sizeof' operator.
>-Do you know if there is a compiler operator like above, or is there any
>-alternative solution.
>
>Standard C provides an offsetof() macro, but you don't really need one.
>	struct a_struct foo;
>	int offset2 = (char *)&foo.member2 - (char *)&foo; /* for example */

Here's how *they* do in the X Window System.  I expect it's about as
portable as anything gets.  This is lifted straight from Intrinsic.h.
And BTW, they use it often.

#if defined(CRAY) || defined(__arm)
#ifdef CRAY2

#define XtOffset(p_type,field) \
    (sizeof(int)*((unsigned int)&(((p_type)NULL)->field)))

#else   /* !CRAY2 */

#define XtOffset(p_type,field) ((unsigned int)&(((p_type)NULL)->field))

#endif  /* !CRAY2 */
#else   /* ! (CRAY || __arm) */

#define XtOffset(p_type,field) \
    ((Cardinal) (((char *) (&(((p_type)NULL)->field))) - ((char *) NULL)))

#endif /* !CRAY */

#define XtOffsetOf(s_type,field) XtOffset(s_type*,field)

#ifdef notdef
/* this doesn't work on picky compilers */
#define XtOffset(p_type,field)  ((unsigned int)&(((p_type)NULL)->field))
#endif


-- 
Kaleb Keithley                        kaleb@thyme.jpl.nasa.gov

Meep Meep                             Roadrunner
Veep veep                             Quayle

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (05/21/91)

In article <1276@unisql.UUCP> pckim@unisql.UUCP (Pyung-Chul Kim) writes:
> can I get the offset of member2 at *compiling time* and *portably* ?

In article <16194@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
> Yes, but you shouldn't very often need to do so.
> Standard C provides an offsetof() macro, but you don't really need one.

In article <1991May20.201857.635@lynx.CS.ORST.EDU>, osbornk@mist.CS.ORST.EDU (Kasey S. Osborn) writes:
> Really?  I can't find a reference to offsetof() in any of my C references.
> In fact, GNU CC does not preprocess offsetof() and instead treats it as an
> external reference.  Are you sure this is standard?

It sounds as though you need some up-to-date C references.
The little Plauger & Brodie handbook is cheap and excellent.

The GNU C compiler *does* understand offsetof, *provided* you #include
the right header file.  Doug Gwyn wrote "Standard C provides an
offsetof() MACRO" and he chose his words carefully.  *None* of the
standard C macros is available *unless* you #include an appropriate
header file.  In this case the file in question is <stddef.h>,
and our copy of GCC certainly has it.

> What compiler are you using?  What is the syntax of offsetof()?

	offsetof(TYPE, MEMBER)

where TYPE is a type (either a typedef id or 'struct Tag'),
not a structure tag.  Example:

    #include <stddef.h>

    struct a_struct
	{
	    short member1;
	    char  member2;
	    int   member3;
	};

    typedef struct a_struct a_type;

    main()
	{
	    printf("%d %d %d\n",
		offsetof(struct a_struct, member1),
		offsetof(struct a_struct, member2),
		offsetof(a_type, member3));
	    exit(0);
	}

On an Encore Multimax I get the output "0 2 4".
-- 
There is no such thing as a balanced ecology; ecosystems are chaotic.

gwyn@smoke.brl.mil (Doug Gwyn) (05/21/91)

In article <1991May20.201857.635@lynx.CS.ORST.EDU> osbornk@mist.CS.ORST.EDU (Kasey S. Osborn) writes:
-In article <16194@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
-|Standard C provides an offsetof() macro, ...
-Really?  I can't find a reference to offsetof() in any of my C references.
-In fact, GNU CC does not preprocess offsetof() and instead treats it as an
-external reference.  Are you sure this is standard?

Jesus, what a stupid question.

-What compiler are you using?  What is the syntax of offsetof()?  I've
-been trying to find a palatable solution to this problem with no luck.

Why don't you try looking in the index of the C standard?

gwyn@smoke.brl.mil (Doug Gwyn) (05/21/91)

In article <1991May20.212338.24349@thyme.jpl.nasa.gov> kaleb@thyme.jpl.nasa.gov (Kaleb Keithley) writes:
>In article <16194@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
>>In article <1276@unisql.UUCP> pckim@unisql.UUCP (Pyung-Chul Kim) writes:
>>-can I get the offset of member2 at *compiling time* and *portably* ?
>>Yes, but you shouldn't very often need to do so.
>Opinion or Fact?

Both.

>Here's how *they* do in the X Window System.  I expect it's about as
>portable as anything gets.

Wrong!  I posted a portable method.

dbrooks@osf.org (David Brooks) (05/21/91)

In article <16211@smoke.brl.mil>, gwyn@smoke.brl.mil (Doug Gwyn) writes:
|> In article <1991May20.212338.24349@thyme.jpl.nasa.gov> kaleb@thyme.jpl.nasa.gov (Kaleb Keithley) writes:
|> >Here's how *they* do in the X Window System.  I expect it's about as
|> >portable as anything gets.
|> 
|> Wrong!  I posted a portable method.

The method you posted:
	struct a_struct foo;
	int offset2 = (char *)&foo.member2 - (char *)&foo; /* for example */

has an unfortunate drawback.  You need to be able to declare foo, and
squander space for it.  The ubiquitous uses in X don't have those luxuries.
-- 
David Brooks				dbrooks@osf.org
Systems Engineering, OSF		uunet!osf.org!dbrooks

gwyn@smoke.brl.mil (Doug Gwyn) (05/22/91)

In article <22051@paperboy.OSF.ORG> dbrooks@osf.org (David Brooks) writes:
>The method you posted:
>	struct a_struct foo;
>	int offset2 = (char *)&foo.member2 - (char *)&foo; /* for example */
>has an unfortunate drawback.  You need to be able to declare foo, and
>squander space for it.  The ubiquitous uses in X don't have those luxuries.

No, you don't.  If you understood my example, you should be able to apply
the technique whenever you can latch onto, for example, a pointer to a
struct of the appropriate type.

The X11 source code style is ATROCIOUS and should not be used as a model.

dbrooks@osf.org (David Brooks) (05/22/91)

In article <16220@smoke.brl.mil>, gwyn@smoke.brl.mil (Doug Gwyn) writes:
|> In article <22051@paperboy.OSF.ORG> dbrooks@osf.org (David Brooks) writes:
|> >The method you posted:
|> >	struct a_struct foo;
|> >	int offset2 = (char *)&foo.member2 - (char *)&foo; /* for example */
|> >has an unfortunate drawback.  You need to be able to declare foo, and
|> >squander space for it.  The ubiquitous uses in X don't have those luxuries.
|> 
|> No, you don't.  If you understood my example, you should be able to apply
|> the technique whenever you can latch onto, for example, a pointer to a
|> struct of the appropriate type.

As I said, the ubiquitous uses in X don't have that luxury.

|> The X11 source code style is ATROCIOUS and should not be used as a model.

Oh, I agree with that.  Looking at the macro, I'm always astounded that it
works.

However, the fact is, in two years of supporting folks using X, I've never
come across a pre-ANSI compiler that failed to handle the X macro.  And,
for ANSI compilers, with an official offsetof, it's moot.
-- 
David Brooks				dbrooks@osf.org
Systems Engineering, OSF		uunet!osf.org!dbrooks

gwyn@smoke.brl.mil (Doug Gwyn) (05/23/91)

In article <22103@paperboy.OSF.ORG> dbrooks@osf.org (David Brooks) writes:
>In article <16220@smoke.brl.mil>, gwyn@smoke.brl.mil (Doug Gwyn) writes:
>|> ...  If you understood my example, you should be able to apply
>|> the technique whenever you can latch onto, for example, a pointer to a
>|> struct of the appropriate type.
>As I said, the ubiquitous uses in X don't have that luxury.

But that's merely a design botch, because in order to ask for the offset
of a structure member one HAS to have a particular structure type in mind;
to make any use of the information one has to have a suitable pointer at
hand.  (The design botch is analogous to Berkeley's CTRL(x) macro.)

dbrooks@osf.org (David Brooks) (05/23/91)

In article <16236@smoke.brl.mil>, gwyn@smoke.brl.mil (Doug Gwyn) writes:
|> But that's merely a design botch, because in order to ask for the offset
|> of a structure member one HAS to have a particular structure type in mind;
|> to make any use of the information one has to have a suitable pointer at
|> hand.

This is probably dragging the point out too far, but no.  The XtOffset
macro is used to initialize a static array-of-struct.  There is no reason
to have a variable of the struct type in scope.  The table information is
used by a generic procedure compiled separately, to fill in information
from an outside database using code that is probably itself non-portable-
but-invariably-works.

In practice, there are local variables of the same type later in the source
file, but they don't *have* to be there.  They too could be separately
compiled.

As I said, I agree it's a design botch, and it's nice to have ANSI define
offsetof, but it is all done with good intentions, in the interests of
information hiding.
-- 
David Brooks				dbrooks@osf.org
Systems Engineering, OSF		uunet!osf.org!dbrooks

gwyn@smoke.brl.mil (Doug Gwyn) (05/24/91)

In article <22138@paperboy.OSF.ORG> dbrooks@osf.org (David Brooks) writes:
-In article <16236@smoke.brl.mil>, gwyn@smoke.brl.mil (Doug Gwyn) writes:
-|> But that's merely a design botch, because in order to ask for the offset
-|> of a structure member one HAS to have a particular structure type in mind;
-|> to make any use of the information one has to have a suitable pointer at
-|> hand.
-This is probably dragging the point out too far, but no.  The XtOffset
-macro is used to initialize a static array-of-struct.  There is no reason
-to have a variable of the struct type in scope.

But the programmer can easily MAKE one simply by casting the polymorphic
array member type to whatever is being assumed for each use of the offset
macro in the initializer.  The "handle" needed is present, albeit not in
the final form you want.

dmj@cunixa.cc.columbia.edu (Douglas M Jaffe) (05/25/91)

In article <1991May20.201857.635@lynx.CS.ORST.EDU> osbornk@mist.CS.ORST.EDU (Kasey S. Osborn) writes:
>In article <16194@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
>|In article <1276@unisql.UUCP> pckim@unisql.UUCP (Pyung-Chul Kim) writes:
>|-struct a_struct {
>|-short    member1;
>|-char  member2;
>|-int   member3;
>|-};
>|-can I get the offset of member2 at *compiling time* and *portably* ?
>|
>|Yes, but you shouldn't very often need to do so.
>|
>|-It is possible to provide a compiler operator:
>|- offsetof(member_name,structure_type_name)
>|-as it provides 'sizeof' operator.
>|-Do you know if there is a compiler operator like above, or is there any
>|-alternative solution.
>|
>|Standard C provides an offsetof() macro, but you don't really need one.
>|  struct a_struct foo;
>|  int offset2 = (char *)&foo.member2 - (char *)&foo; /* for example */
>
>Really?  I can't find a reference to offsetof() in any of my C references.
>In fact, GNU CC does not preprocess offsetof() and instead treats it as an
>external reference.  Are you sure this is standard?
>
>What compiler are you using?  What is the syntax of offsetof()?  I've
>been trying to find a palatable solution to this problem with no luck.


i have to check my ansi reference for offsetof().  however, i wouldn't
rely on the assumption that offsetof() will exist in every 
__STDC__ (stupid c) compiler that you encounter.  you might want 
to consider adding the following macros to your bag of tricks.
these offset macros should work in almost _every_ c  compiler/interpreter that 
exists:  from msc, turboc, SunOS cc, rs/6000 xlc, to tandem (yes, tandem) c.

NOTES
-----
1.  i wrote these many years ago, on a buggy ibm-pc (yes, p. c. !) compiler.
2.  because of #1, i had to code like a prude, with parens all over.
3.  these macros have been working ever since.
4.  don't flame me on the parameter names that i used!


======================================================================

#define FAKE_ADDR  ((char *) 256)

/* offset to start of field */
#define OFFSET_TO(tttt,mmmm)    \
    (((unsigned long)  (&(((tttt *)(FAKE_ADDR))->mmmm) )) - \
     ((unsigned long)  ((tttt *)(FAKE_ADDR))))

/* size from start of struct to end of mentioned member */
#define SIZE_TOEND(t,m) \
    (OFFSET_TO(t,m) + sizeof(((t *)(FAKE_ADDR))->m))

/* offset of last byte of mentioned member from start of struct */
#define OFFSET_TOEND(t,m) (SIZE_TOEND(t,m) - (unsigned long)1)


----------------------------------------------------------------------
             _
  ,---------'_)
 (_/\  O O  /
     \  v  /  
      \___/
        U

  "doggie fresh"

sef@kithrup.COM (Sean Eric Fagan) (05/29/91)

In article <1991May25.054608.6647@cunixf.cc.columbia.edu> dmj@cunixa.cc.columbia.edu (Douglas M Jaffe) writes:
>i have to check my ansi reference for offsetof().  however, i wouldn't
>rely on the assumption that offsetof() will exist in every 
>__STDC__ (stupid c) compiler that you encounter.  

I would, since it's part of ANSI, and I'd rely on it as much as I would
vfprintf.

Grab your nearest ANSI C document, and look at what's in <stddef.h>

-- 
Sean Eric Fagan  | "I made the universe, but please don't blame me for it;
sef@kithrup.COM  |  I had a bellyache at the time."
-----------------+           -- The Turtle (Stephen King, _It_)
Any opinions expressed are my own, and generally unpopular with others.