arne@yc.estec.nl (Arne Lundberg) (01/02/90)
I am trying to write some code that tries to access members in a structure by knowing the start address and the offset to a particular member element. The following program shows a small example (the real program does not hardcode the offsets etc.) Is this program legal in ANSI C, will it produce the desired result? The (Non-ANSI) compilers I have tested either gives the value for `a' three times or complains about ``unknown size for pointer to void''. It works perfectly well if I change the type of p to be ``char *''. --------------------------------------- struct x { int a, b, c; } x = { 1, 2, 3 }; main() { void *p = &x; printf("a %d\n", *(int *)(p + 0)); printf("b %d\n", *(int *)(p + 4)); printf("c %d\n", *(int *)(p + 8)); } --------------------------------------- BTW, is it possible to write an ANSI compatible ``offsetof'' macro for traditional C compilers? I am now using the XtOffset macro from the X11/Toolkit but would like to have something that doesn't require an additional name for the ``pointer to the structure'' type. Arne Lundberg European Space Technology Centre, Noordwijk, the Netherlands arne@yc.estec.nl or ALUNDBER@ESTEC.BITNET Phone: +31 1719 84865, Fax: +31 1719 12142, Telex: 39098
henry@utzoo.uucp (Henry Spencer) (01/03/90)
In article <1055@esatst.yc.estec.nl> arne@yc.estec.nl (Arne Lundberg) writes: >...Is this program legal in ANSI C, will it >produce the desired result? No. Pointer arithmetic is not defined for pointer-to-void. It can't be, since it's not possible to do pointer arithmetic without knowing the size of the type pointed to. >BTW, >is it possible to write an ANSI compatible ``offsetof'' macro >for traditional C compilers? ... Sort of. We do this in C News. Here's what we say about it in our porting-problems document (C News enthusiasts: this will be in the next patch): Unfortunately, it is really hard to write a portable version of this. The implementation we currently use is: .DS #define offsetof(type, mem) ((char *)&((type *)NULL)->mem - (char *)NULL) .DE The table in \fIrelay/hdrdefs.c\fR puts invocations of \fIoffsetof\fR in initializers. This turns out to be a severe stress test for C compilers. A compilation error in \fIhdrdefs.c\fR is almost certain to be problems with this macro. Some compilers, notably the one in Microport System V Release 2.3, reject it. We have heard a report that System V Release 2 on the VAX silently miscompiles it! If you have trouble with \fIoffsetof\fR, you might try this version instead: .DS #define offsetof(type, mem) ((int)&((type *)NULL)->mem) .DE -- 1972: Saturn V #15 flight-ready| Henry Spencer at U of Toronto Zoology 1990: birds nesting in engines | uunet!attcan!utzoo!henry henry@zoo.toronto.edu
bill@twwells.com (T. William Wells) (01/03/90)
In article <1055@esatst.yc.estec.nl> arne@yc.estec.nl (Arne Lundberg) writes:
:
: I am trying to write some code that tries to access members in a structure
: by knowing the start address and the offset to a particular member element.
: The following program shows a small example (the real program does not
: hardcode the offsets etc.) Is this program legal in ANSI C, will it
: produce the desired result?
:
: The (Non-ANSI) compilers I have tested either gives the value for `a'
: three times or complains about ``unknown size for pointer to void''.
: It works perfectly well if I change the type of p to be ``char *''.
:
: ---------------------------------------
: struct x {
: int a, b, c;
: } x = {
: 1, 2, 3
: };
:
: main()
: {
: void *p = &x;
: printf("a %d\n", *(int *)(p + 0));
: printf("b %d\n", *(int *)(p + 4));
: printf("c %d\n", *(int *)(p + 8));
: }
: ---------------------------------------
This is not legal ANSI C. About the only things you can do with
void * are cast them, assign them, and pass them as function
arguments.
: is it possible to write an ANSI compatible ``offsetof'' macro
: for traditional C compilers?
There is no way to write an offsetof macro that will work on all
compilers. There are a number of ways to write it that will work
on most non-ANSI compilers.
---
Bill { uunet | novavax | ankh | sunvice } !twwells!bill
bill@twwells.com
bts@sas.UUCP (Brian T. Schellenberger) (01/07/90)
In article <1990Jan3.073624.14061@twwells.com> bill@twwells.com (T. William Wells) writes: |In article <1055@esatst.yc.estec.nl> arne@yc.estec.nl (Arne Lundberg) writes: |: |: I am trying to write some code that tries to access members in a structure |: by knowing the start address and the offset to a particular member element. |: The following program shows a small example (the real program does not |: hardcode the offsets etc.) Is this program legal in ANSI C, will it |: produce the desired result? |: |: The (Non-ANSI) compilers I have tested either gives the value for `a' |: three times or complains about ``unknown size for pointer to void''. |: It works perfectly well if I change the type of p to be ``char *''. |: |: --------------------------------------- |: struct x { |: int a, b, c; |: } x = { |: 1, 2, 3 |: }; |: |: main() |: { |: void *p = &x; |: printf("a %d\n", *(int *)(p + 0)); |: printf("b %d\n", *(int *)(p + 4)); |: printf("c %d\n", *(int *)(p + 8)); |: } |: --------------------------------------- . . . so just use "char *"; this works under ANSI, too. 1. offsetof is the size in bytes. (4.1.5) 2. sizeof yields the sie in bytes; When applied to char . . . the result is 1. (3.3.3.4) 3. A pointer to void shall htave the representation and alignment requirements as a pointer to character type (3.1.2.5, the paragraph just before examples). Ergo, this must work under ANSI with char *. -- -- Brian, the Man from Babble-on. ...!mcnc!rti!sas!bts -- (Brian Schellenberger) "No one will ever write a song called 'Nitro Burning Funny Cars'" -- THE DEAD MILKMEN, "Nitro Burning Funny Cars"