[comp.lang.c] summary of obfuscated code request

woodman@sumax.UUCP (David Woodman) (12/06/89)

I want to thank all the people who took time to reply to my question.

Here is a summary of best answers to the current 'obfuscated code' query:
The question:  What does this typecast do?

   struct MYSTRUCT someVariable;
   someVariable = (*((struct MYSTRUCT *)(*)()_msg))(parameters,...);


I received two answers as follows:


/**********************************************************************/
From: uw-beaver!ames.arc.nasa.gov!atari!kbad (Ken Badertscher)
Subject: Re: Obfuscated code

When unraveling wierd and wonderful typecasts such as the above, it's
often best to start in the _middle_ rather than the beginning, as you
tried.

The point of Cox's discussion in the book, if I recall correctly, is
that C is powerful enough for OOP because of the flexibility of
identifiers.  What he does in this example, is warp the meaning of the
identifier _msg, which starts out as a function returning id.

He wants _msg to return a struct MYSTRUCT *, rather than an id, so he
uses a function cast:

 (struct MYSTRUCT *)(*)()
                    ^^^^^-- "pointer to function" type
 ^^^^^^^^^^^^^^^^^^^------- return type of function

This means, "cast the following identifier to a pointer to a function
returning struct MYSTRUCT *."  The identifier being cast is _msg.

So now he has turned _msg into a function pointer, and in order to
invoke it, he must give it arguments:

 ((struct MYSTRUCT *)(*)()_msg)( parameters,...)

Annnnd, since he's assigning the return value to a struct, he needs
to dereference the pointer returned by this function:

 someVariable = (*((struct MYSTRUCT *)(*)()_msg))( parameters,...);

Voila!  Feel free to post this info back to comp.lang.c, if you desire.

  Regards,
  Ken Badertscher
  Atari Corp. System Software Engine

/**********************************************************************/
X-Origin: The Portal System (TM)
X-Possible-Reply-Path: Tim_N_Roberts@cup.portal.com
X-Possible-Reply-Path: sun!portal!cup.portal.com!Tim_N_Roberts

Detangling a type definition or a cast is a tough thing.

You basically work from the inside out.

    (*((struct MYSTRUCT *)(*)() _msg))
       ^^^^^^^^^^^^^^^^^^^^^^^^ 
       This is the cast.  Lets take it apart piece by piece.

   (struct MYSTRUCT *)(*)()
                      ^^^      Cast to a pointer to...
                         ^^     a function ...
   ^^^^^^^^^^^^^^^^^^^           returning a pointer to MYSTRUCT

If you had that cast typedef-ed to "pfmy", you could rewrite the call as:

    (*(pfmy)_msg)(arguments)

which makes a little more sense; the name "_msg" without any arguments is
a "pointer to function".  We are casting that to a "pointer to function
returning MYSTRUCT".  We then dereference that to come up with a "function
returning MYSTRUCT" and pass it the appropriate arguments.

Note that pre-ANSI compilers do not require (some do not allow!) the very
first "*" in the original statement; they automatically dereference 
pointers-to-functions by calling the function.

The Microsoft C Language Reference has an excellent discussion on
constructing and deciphering type definitions and casts.

TNR@cup.portal.com                |  I Survived The
...!sun!portal!cup.portal.com!tnr |  Great Quake of '89.

/**********************************************************************/

-- 
------------------------------------------------------------------------
David Woodman          MAIL: woodman%sumax.uucp@beaver.cs.washington.edu
Seattle University     #include <disclaimer.std>