Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Macro Help

Status
Not open for further replies.

noIQ

Programmer
Feb 24, 2003
2
US
this question was proposed by an employee at Electronic Arts. (is it a trick question? what can this possibly do?)

What does the following macro do? How and why might it be used?

#define MAKE_COOL_GAMES(z, w) (int)(&(((z *)0)->w))


any help would be great!
 
Looks like it finds the offset of a certain member of a class.

As an example, say you have the following type:

Code:
typedef struct
{
    int   first;
    float second;
    char  third;
} type_t;


Then this

Code:
MAKE_COOL_GAMES( type_t, third );

would expand to this

Code:
(int)(&(((type_t *)0)->third));

That line first casts 0 (zero) to a type_t*. That means you have a pointer to a hypothetical object of type type_t, and it's pointing to location 0 (you'll see why in a second).

Next, it gets the "third" member of that hypothetical object by using the arrow operator.

It takes the address of that member, which, since this object (which doesn't really exist) is at memory address 0, is actually the offset of that member from the beginning address of the object.

In this case, if int and float take 4 bytes each, the offset of "third" would probably be 8.

Finally, it casts the result to an int, probably to supress compiler warnings about using a pointer as an integer.

As for what this code is useful for, probably not much. All I can tell you is for finding the offset exactly instead of having to guess it. I know it's a standard C macro (called offsetof, not MAKE_COOL_GAMES). Perhaps someone else can tell you exactly why it's there.
 
looks to me that there was a typo in the macro and it is the zero part mentioned by chip. Most likely, when the parens were happening, the shift was not held down and this was overlooked. Whatever type z is, is being cast to a null pointer (as mentioned) and the -> will immediately give you a null pointer problem when you try to access w. I dont know why this macro would be designed. It seems like a macro to save typing time but what is it saving you?

// With the zero there, it is still invalid
// removal of the zero does nothing
define MAKE_COOL_GAMES(z, w) (int)(&(((z *)0)->w))

// What I think the intention of the macro was
define MAKE_COOL_GAMES(z, w) (int)( (&z)->w )


Here is an example of its use using the type described by chip

type_t myType;
myType.first = 1;
myType.second = 2.0;
myType.third = '3';

int value = MAKE_COOL_GAMES(myType,first)


But what does this provide you? More typing unless you have long variable names. You can accomplish the same thing with

int value = myType.first;


Hope this provided a bit of insight.

Matt
 
Another thought: The macro could be overcomplicating a simple cast opperation or it is missing a param. If is just trying to cast w as type z, then there is no real need for the macro. If it is simplifying a cast of a type and accessing it's members, there is not need for it either.

If my guesses at the macro's intention are wrong, just explain what it is expected to do.

Thanx
Matt
 
The whole point of high-level languages like C etc. was to make it easier for a human to get a machine to do something. If you manage to make a high level language more complicated to interpret than machine code, then someone somewhere has lost the plot!

Well done all those writers who've suggested simpler ways to achieve what this line might have been intended to achieve.

Of course there's a bit of puzzle-fun in trying to write a line of C that's utterly undecipherable, so sorry if that's what the Electronic Arts person was trying to do.
 
lionelhill,

AMEN!

And i would add that the most likely reason you would need a macro like that: "Hideous Design"

"But, that's just my opinion... I could be wrong"
-pete
 
The zero isn't a typo; it does exactly what I said it does. It removes the need to subtract the starting address of the structure to get the offset.

You won't get a null pointer problem just by taking the address of the unallocated memory; you'd only get a problem if you tried to write to it.

Like I said, the macro returns the offset of a member within a structure. Pop open your stddef.h and search for offsetof and see for yourself; it looks exactly like the definition given.

Obviously, there is or was some use for such a macro, as, like I said before, it's part of the Standard C library.
 
Thanks chipperMDW! Your explanation helped a lot.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top