[net.lang.c] To dereference or not dereference, that is the question

ded@aplvax.UUCP (Don E. Davis) (03/03/86)

In article <857@pucc-j> aaz@pucc-j.UUCP (Marc Mengel) writes:
>
>char foo[BIGNUM];
>main()
>{
>        int result;
>
>	/* code to put machine code into foo[] */
>
>	result = (* (int (*)()) foo)();
>}
>-- 

An interesting corollary to this issue is the following.  It
doesn't seem to matter if I deference function pointers or not.
This seems wrong to me.  I feel the y(2) and ((int (*)())x)(3) function 
invocations should be illegal.

#include <stdio.h>
main(argc, argv)
int argc;
char **argv;
{
	int x;
	int (*y)();	/* y is pointer to function returning int */
	int func();

	y = func;	/* y points to func */
	(*y)(1);	/* dereference y and invoke func */
	y(2);		/* DON'T dereference y and invoke func! */

	/* the same as above with casting */
	x = (int)func;
	((int (*)())x)(3);
	(*(int (*)())x)(4);
	exit(0);
}
func(param)
int param;
{
	printf("hello %d\n", param);
}


All of the above appear to be equivalent.  What the heck is going on here?
-- 

					Don Davis
					JHU/APL
				...decvax!harpo!seismo!umcp-cs!aplcen!aplvax!ded
				...rlgvax!cvl!umcp-cs!aplcen!aplvax!ded

chris@umcp-cs.UUCP (Chris Torek) (03/04/86)

In article <196@aplvax.UUCP> ded@aplvax.UUCP (Don E. Davis) writes:

>... It doesn't seem to matter if I deference function pointers or not.
>This seems wrong to me.

... followed by a code sample including the declaration and call:

	int (*y)();
	...
	y(2);

The call is wrong.  It `just happens' to work in PCC-based compilers.
Try compiling the following:

	main()
	{
		int f(), (*p)();

		p = f;
		p(1);
		(*p)(2);
		(**p)(3);
		(****************p)(4);
	}

	f(x)
		int x;
	{

		printf("%d\n", x);
	}

Just because it works in your compiler (and in mine) does not mean
it is correct....

Of course, the only thing you can do with a pointer to a function
is take its address, take its value, or call through it.  PCC seems
to figure that if you are not doing either of the former, you must
be doing the latter, and does not care how many indirections were
actually used.  While this is a bug in PCC, it does not seem a very
important one.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1415)
UUCP:	seismo!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@mimsy.umd.edu

kwh@bentley.UUCP (KW Heuer) (03/07/86)

In article <44@umcp-cs.UUCP> umcp-cs!chris (Chris Torek) writes:
>		int f(), (*p)();
>		p = f;
>		p(1);
>		(*p)(2);
>		(**p)(3);
>		(****************p)(4);

Although there is no excuse for "p(1)", the other three examples are
in fact correct.  Recall that there are only two things you can do
with a function (not a pointer): call it (as in f()) or take its
address (any other use of the name).  Thus "p = f" takes the address
of function f and stores it in pointer p.

Now consider "(**p)(3)".  "*p" is of type _function_, but it is not
being called (since the next operator is "*" rather than "()"), so
we have to take its address.  This leaves us with
	(* pointer_to_function)(3)
which is legal.  Each time you add a "*" you convert a pointer into
a function, but if you don't immediately call it, you are taking its
address again.

Similarly, you could write "(*exit)(0)".  For these reasons I think
the address operator should have been required, "p = &f"; as the
language stands it is permitted but discouraged (lint warns).