[comp.lang.c] OFFSET -macro

ncpg@ehviea.ine.philips.nl (ncpg) (11/27/90)

I have a problem with "C" and its portability.
Our department is developing software in microsoft C 5.1.
When the software is tested, it is compiled with the Intel
protected mode compiler (ic286).

The problem can be described as follow:

I want to know the offset of a field within a structure.
This offset is used as an argument to a data base function, which
will use it to determine the key within the structure to select
an element.

struct x{
	int a;
	char b;
	short key;
	.
	.
} X;

X *t;
short key;

t = DataBaseGet(DataBase, &key, sizeof(key), OFFSET(X, key));

In Microsoft 5.1, I declared the following macro:

I:
#define	OFFSET(struct, field)	((unsigned short)(&(((struct*)0)->field)))

This (Nice) macro is standard on Microsoft 6.0 and it works.
The Intel Compiler gives warnings, so I tried something else:

II:
#define	OFFSET(structPtr, field)	((unsigned short) \
					(&((char *)(structPtr->field))) - \
					&((char *)(structPtr)))

t = DataBaseSeek(DataBase, &key, sizeof(key), OFFSET(t, key));

This offset will compile on both machines, but at run time in
protected mode (intel C), t is pointer to a structure X and is not initialized.
OFFSET is now referring to an invalid address so I get a run-time error.

When I want to use II, I need to declare a variable (of type structure)
which is used only for this purpose. This is not acceptable.

Another possibility is is to hide this variable:

III:
#define OFFSET(struct, field, result) \
				{ \
					struct tmp; \
					result = (int)((char *)&tmp.field - (char *)&tmp); \
				}

The disadvantage of this methode is that it cannot be used as an argument
in a function call, so a temporary variable is needed, to store the result.


Is there anybody out there, that can help me.

Thanks in advance....
                        Tony de Goede & Guido van Rooij

gwyn@smoke.brl.mil (Doug Gwyn) (11/28/90)

In article <898@ehviea.ine.philips.nl> ncpg@ehviea.ine.philips.nl (ncpg) writes:
>#define	OFFSET(structPtr, field)	((unsigned short) \
>					(&((char *)(structPtr->field))) - \
>					&((char *)(structPtr)))

This wouldn't be right anyway.  It's &structPtr->field that you want to
use; you cannot apply & to the result of an object cast because it's not
an lvalue.