[comp.lang.c] procedure pointer question

cogen@XN.LL.MIT.EDU (David Cogen) (01/15/88)

Consider the following fragment:

{
  double sin ();
  double (*fun) ();

  fun = sin;
  printf ("%f %f", fun(1), (*fun)(1));
}

Both invocations of fun work and give the correct result. But it seems that one
of the invocations is wrong (the first). Why do they both work? Will they always
work in all cases?

-- 
|-|-----|-|-----|-|
| |David S Cogen| |
|-|-----|-|-----|-|

chris@mimsy.UUCP (Chris Torek) (01/16/88)

In article <861@xn.LL.MIT.EDU> cogen@XN.LL.MIT.EDU (David Cogen) writes:
-  double sin ();
-  double (*fun) ();
-
-  fun = sin;
-  printf ("%f %f", fun(1), (*fun)(1));
-
-Both invocations of fun work and give the correct result. But it seems that one
-of the invocations is wrong (the first). Why do they both work?

The first one is not allowed by K&R, but is allowed by the dpANS.  The
first invocation works because PCC lets it work.  (And what the compiler
does defines the language :-) ... well, this time.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/16/88)

In article <861@xn.LL.MIT.EDU> cogen@XN.LL.MIT.EDU (David Cogen) writes:
>Both invocations of fun work and give the correct result.

In almost all contexts, the function designator (i.e. name) is
converted into a pointer to the function.  When you call a function,
the thing before the "(arguments)" part it is required to be a
pointer to a function of appropriate type.  This is what some
current C compilers actually do and is what X3J11 decided on for
the ANSI C standard.  However, it's not how K&R described it.

Note that the following invocations will all be valid and all do
the same thing:

	extern double sin( double );
	double x;

	x = sin( 2.0 );
	x = (&sin)( 2.0 );
	x = (*sin)( 2.0 );
	x = (**sin)( 2.0 );
	x = (***sin)( 2.0 );
	/* etc. */

You can do similar things with objects that are explicit pointers-
to-functions.

pardo@june.cs.washington.edu (David Keppel) (01/16/88)

[ (***sin)(x) <=> (**sin)(x) <=> (*sin)(x) <=> (&sin)(x) <=> sin(x) ]

Bleah!  How do I tell the difference between a pointer to a function,
a pointer to a pointer to a function, etc.?

Is this some strange "feature" of the C compiler, is the type of pointer
to function actually "pointer to (pointer to (pointer to (...", or is
there a _reason_ for this?

    ;-D on  (The answer is simple if the question is complex)  Pardo

gwyn@brl-smoke.UUCP (01/16/88)

In article <4002@june.cs.washington.edu> pardo@uw-june.UUCP (David Keppel) writes:
>[ (***sin)(x) <=> (**sin)(x) <=> (*sin)(x) <=> (&sin)(x) <=> sin(x) ]
>Bleah!

This part I understand!

>How do I tell the difference between a pointer to a function,
>a pointer to a pointer to a function, etc.?

But this part I don't -- the above strange property has almost nothing
to do with types.  You still have to declare the types of pointers-to-
functions properly.

>Is this some strange "feature" of the C compiler, is the type of pointer
>to function actually "pointer to (pointer to (pointer to (...", or is
>there a _reason_ for this?

I explained the reasons when I gave the example.  They have to do with
the rules for evaluating expressions.

flaps@dgp.toronto.edu (Alan J Rosenthal) (01/17/88)

In article <4002@june.cs.washington.edu> pardo@uw-june.UUCP (David Keppel) writes:
>
>[ (***sin)(x) <=> (**sin)(x) <=> (*sin)(x) <=> (&sin)(x) <=> sin(x) ]
>
>Bleah!  How do I tell the difference between a pointer to a function,
>a pointer to a pointer to a function, etc.?

Nowadays, a function used in an rvalue context (including as in "f(x)") is
converted to a pointer to that function, much like the array conversion to
a pointer to its zeroth element.  So the () operator takes a pointer to
function, not a function, despite appearances.

If 'f' is a function and appears in an rvalue context, it becomes a pointer
to function.  If it is then dereferenced, it becomes a function, which,
appearing in an rvalue context, is converted to a pointer to function.  This
can therefore be iterated any number of times.

Of course, I still consider it good style to write "(*pf)();" even though
it's not necessary.

ajr

-- 
"noalias considered sailaon"