[comp.lang.c] How to get a byte offset

swie@cs.umn.edu (S. T. Tan) (05/28/90)

Is there an easy way to get the byte offset of a field in a structure without
counting it manually ?
The reason I don't want to count the offset manually is, the size of the 
"int"-type is machine dependent (may be 2 bytes or 4 bytes).

example: struct {
           int	a;
           char	b[3];
           int	c[10];
           char	d;
         } my_struct_type;

What would be the offset of "d" ?

Please e-mail the answer to me directly since it seems to me that the answer is
trivial.

Thanks in advance
swie@umn-cs.cs.umn.edu

cpcahil@virtech.uucp (Conor P. Cahill) (05/28/90)

In article <1990May28.034643.6962@cs.umn.edu> swie@cs.umn.edu (S. T. Tan) writes:
>Is there an easy way to get the byte offset of a field in a structure without
>counting it manually ?

Here are a few examples:

/*
 * the first one works using the structure type name and does not
 * require the runtime existance of any occurance of such a structure.
 * NOTE: this may be non-portable due to the use of a NULL pointer.
 */
#define	offsetof(elem,str)	(&(((struct str *)0)->elem))

/*
 * the following one requires an occurance of the structure itself and 
 * should be relatively portable.
 */

#define myoffset(elem,data)	( ((char *) &data.d) - ((char *)&data) )

struct my_struct_type {
int	a;
char	b[3];
int	c[10];
char	d;
} my_name;


main()
{

	printf( "offsetof(d,my_struct_type) = %d\n",offsetof(d,my_struct_type));
	printf( "myoffset(d,my_name) = %d\n",myoffset(d,my_name));
}

-- 
Conor P. Cahill            (703)430-9247        Virtual Technologies, Inc.,
uunet!virtech!cpcahil                           46030 Manekin Plaza, Suite 160
                                                Sterling, VA 22170 

pmk@craycos.com (Peter Klausler) (05/28/90)

>Is there an easy way to get the byte offset of a field in a structure without
>counting it manually ?

In ANS C, #include <stddef.h> and use the offsetof macro.

If you don't have access to a standard compiler, try this common trick:

#define offsetof(type,member)	((char *) &((type *) 0)->member - (char *) 0)

-Peter Klausler, a compiler guy at Cray Computer Corp. in Colorado Springs

poser@csli.Stanford.EDU (Bill Poser) (05/29/90)

In article <16802@phoenix.Princeton.EDU> pfalstad@phoenix.Princeton.EDU (Paul John Falstad) writes:
>
>The first way is just to add up all the sizeof values of a, b, and c.
>
>  #define D_OFFSET (sizeof(int)+sizeof(char)*3+sizeof(int)*10)

This won't work in general since, in order to satisfy alignment requirements,
a struct may contain padding bytes. For example, on some machines the
structure:

	struct foo{
		char b;
		short a;
	};

will contain 4 bytes because it will be laid out in memory like this:

	0000	b
	0001	PADDING
	0002	low byte of a
	0003	high byte of a

Without the padding a would not begin on an even address, which
is not permitted in some architectures.
							Bill

pfalstad@phoenix.Princeton.EDU (Paul John Falstad) (05/29/90)

In article <16802@phoenix.Princeton.EDU> I write:
>In article <1990May28.034643.6962@cs.umn.edu> swie@cs.umn.edu (S. T. Tan) writes:
>>Is there an easy way to get the byte offset of a field in a structure without
>>counting it manually ?
>The first way is just to add up all the sizeof values of a, b, and c.

Oops #1:  This doesn't work, since there might be padding.  (It was
a stupid suggestion anyway, and unnecessary, as it turns out.)

Oops #2:

>  d_offset = (char *) &foo->d - (char *) foo;
>Of course, the result isn't a constant, and code is generated.  You

Well, I'm not sure about the above example, but even Manx got this right:

#define d_offset ((int) &(((struct foo *) 0)->d))

The result IS an integer constant.  You can even use it for an array size,
although it may not be portable because of the NULL pointer.

-- 
Paul Falstad  PLINK:Hypnos GEnie:P.FALSTAD net:pfalstad@phoenix.princeton.edu
Disclaimer: My opinions, which belong to me and which I own, are mine.
-Anne Elk (not AN elk!)  The sun never set on the British empire because
the British empire was in the East and the sun sets in the West.

jharkins@sagpd1.UUCP (Jim Harkins) (06/02/90)

In article <1990May28.034643.6962@cs.umn.edu> swie@cs.umn.edu (S. T. Tan) writes:
>Is there an easy way to get the byte offset of a field in a structure without
>counting it manually ?

This is one of my minor pet peeves.  Why don't you just use the field name?
No matter how you count the offset, if anybody in the future changes the
structure then your code just broke.  The only valid reason that I can think
of for using an offset is that your passing the data structure to a routine
written in another language.  Even then, most languages (including modern
assemblers) provide methods of declaring structures and a little bit of fiddling
around takes care of things like padding.

>The reason I don't want to count the offset manually is, the size of the 
>"int"-type is machine dependent (may be 2 bytes or 4 bytes).

Thats exactly my point.  Being something of a snot, if I ever find someone
on my project counting byte offsets instead of using field names then I go
in and change the structure, ensureing I do so in such a way that all their
stuff breaks.  Then when they bitch at me about working weekends to fix
previously working code I can smile and walk away.  I repeat as needed, and
I've never had a problem with a boss in doing this.

Against my own good judgement, a good way to get the offset is to:

	char *head, *body;
	int offset;

	head = (char *) &structure;
	body = (char *) &structure.field_name;
	offset = body - head;

But please don't use this in your code.


-- 
jim		jharkins@sagpd1

I hate to see you go, but I love to see you walk away.

karl@haddock.ima.isc.com (Karl Heuer) (06/05/90)

In article <1990May28.131914.11205@virtech.uucp> cpcahil@virtech.UUCP (Conor P. Cahill) writes:
>In article <1990May28.034643.6962@cs.umn.edu> swie@cs.umn.edu (S. T. Tan) writes:
>>Is there an easy way to get the byte offset of a field in a structure without
>>counting it manually ?

In ANSI C, you use the macro offsetof(), which you import from <stddef.h>.
If you don't have it, you have to roll your own.  There is no portable
definition which is guaranteed to evaluate to a compile-time constant, but
for any particular machine it's likely that one or more of the versions posted
here will happen to work.

>Here are a few examples:
>#define offsetof(elem,str) (&(((struct str *)0)->elem))

The args are in the wrong order, and the one named `str' has to be a struct
tag rather than a type.  (If you have to reinvent the wheel, you might as well
make it consistent with everybody else's wheel, especially if you use the same
name.)  Also, the result is a pointer; it ought to be an integer.  Some better
choices are:
	#define offsetof(T,mem) ((size_t)(char *)&((T *)0)->mem)
	#define offsetof(T,mem) ((char *)&((T *)0)->mem - (char *)0)
	#define offsetof(T,mem) ((char *)&((T *)&X)->mem - (char *)&X)
In the third one, X is any convenient object.

Karl W. Z. Heuer (karl@ima.ima.isc.com or harvard!ima!karl), The Walking Lint