[comp.std.c] pointers to functions, dereferencing, first byte of func

don@dgbt.doc.ca (Donald McLachlan) (01/30/91)

I recently wanted to write a nastly bit of code for a PC (self modifying)
so ...

char *c;
extern char func();

c = func;

some code putting new hex values into the address space of the function


now for the fun stuff. Under microsoft C, c[1] ... c[MAX_INT] worked,
but c[0] would sometimes bugger me up. *c had the exact same unreliable
results (as it should since *c is supposed to be identicle to c[0]).

what I had to do to get at the first byte of executable code was ...
char *c1;

c1 = &(c[1]);
--c1;		/* should equal c[0] */
*c1 = char constant.

hows that for bastardising code to fool a compiler!!!

gwyn@smoke.brl.mil (Doug Gwyn) (01/31/91)

In article <1991Jan30.031315.9427@dgbt.doc.ca> don@dgbt.doc.ca (Donald McLachlan) writes:
-char *c;
-extern char func();
-c = func;
-what I had to do to get at the first byte of executable code was ...
-char *c1;
-c1 = &(c[1]);
---c1;		/* should equal c[0] */
-*c1 = char constant.

This seems to me to have nothing to do with Standard C...

bhoughto@pima.intel.com (Blair P. Houghton) (02/01/91)

In article <15020@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
>In article <1991Jan30.031315.9427@dgbt.doc.ca> don@dgbt.doc.ca (Donald McLachlan) writes:
>-char *c;
>-extern char func();
>-c = func;
>-what I had to do to get at the first byte of executable code was ...
>
>This seems to me to have nothing to do with Standard C...

Oh yes it does.  It has to do with violating portability,
misunderstanding the meaning of "pointer to function,"
and illegally assigning values between incompatible types.

Firstly, (char *) and (char *()) are vastly different
types.  There are no guarantees as to size and alignment
matching.  Assigning the value of a (char *()) to a (char *)
is as bad as assigning an (unsigned register long *)
to a (double).

Secondly, you cannot dereference a pointer to a function.
You can only assign it to other variables of compatible
type and use it to call a function.  When calling as
`(*fp)()', the `(*fp)' part is termed the "function
designator."[*]  It is not an lvalue and can therefore not
reference objects.  `fp' is less a pointer and more a proxy
for an anonymous identifier.

Finally, There's no responsibility on the part of the platform to
map the "pointer to function" to any dereferencible location.
(However, nothing prohibits giving definition to undefined
behavior, and a purposefully nonconforming program operating
with cloying compiler-chumminess might take advantage of it.)

[*] Function designator is defined in ANSI X3.159-1989,
sec. 3.2.2.1, "Lvalues and Function Designators."
See also:
           3.3.2.2, "Function Calls"
           3.3.3.2, "Address and Indirection Operators"
           3.1.2.6, "Compatible Type and Composite Type"

				--Blair
				  "So if you add pointers to the
				   two functions f() and g(),
				   do you get f(g()) or g(f())?"