[comp.lang.c] address of function

maart@cs.vu.nl (Maarten Litmaath) (06/07/89)

Why weren't function pointers handled the way below?

	int	foo(), (*bar)() = &foo;

ANSI has fixed this, right?
-- 
 "Your password [should be] like your |Maarten Litmaath @ VU Amsterdam:
      toothbrush." (Don Alvarez)      |maart@cs.vu.nl, mcvax!botter!maart

gwyn@smoke.BRL.MIL (Doug Gwyn) (06/08/89)

In article <2700@solo8.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes:
>Why weren't function pointers handled the way below?
>	int	foo(), (*bar)() = &foo;
>ANSI has fixed this, right?

It's not feasible to fix something in widespread correct usage.
A function designator gets turned into a pointer to the function
in all contexts except as the operand of sizeof or &.  The latter
makes your example correct, although apparently some existing
compilers disallowed use of & in that context.

kt@msor.UUCP (Keith Tizzard) (06/12/89)

In article <2700@solo8.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes:
>Why weren't function pointers handled the way below?
>
>	int	foo(), (*bar)() = &foo;
>
>ANSI has fixed this, right?


 ... and does ANSI permit the following ?

	int	this[100], *that = &this;

I was under the impression that there was a symmetry between functions and
arrays.

karl@haddock.ima.isc.com (Karl Heuer) (06/13/89)

In article <370@msor0.UUCP> kt@msor0.UUCP (Keith Tizzard) writes:
>... and does ANSI permit the following ?
>	int	this[100], *that = &this;
>I was under the impression that there was a symmetry between functions and
>arrays.

The symmetry you're looking for is there, but your example isn't analogous to
Maarten's.  It does work to write
	int  this[100], (*that)[100] = &this;
which is analogous to
	int  foo(void), (*bar)(void) = &foo;

This particular symmetry holds only if the explicit "&" is used.  Writing
"this" without the ampersand yields the same as "&this", but writing "foo"
without the ampersand yields "&foo[0]", which is not the same as "&foo".
(Though they will compare equal if brought to a common type.)

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

guy@auspex.auspex.com (Guy Harris) (06/13/89)

> ... and does ANSI permit the following ?
>
>	int	this[100], *that = &this;

No.  It does permit

	int	this[100], (*that)[100] = &this;

since "&this" is a pointer to "this", and "this" is an array of 100
"int"s, so "&this" is a pointer to an array of 100 "int"s (not a pointer
ot a single "int" - yes, the type "pointer to array" exists, and

	int	(*that)[100];

declares "that" to have type "pointer to array of 100 "int"s).

chad@lakesys.UUCP (D. Chadwick Gibbons) (06/13/89)

In article <370@msor0.UUCP> kt@msor0.UUCP (Keith Tizzard) writes:
| ... and does ANSI permit the following ?
|	int	this[100], *that = &this;

	Not exactly; more like:

	int this[100], *that = this;

		-or-

	int this[100], *that = &this[0];

As with a function, the name by itself implies the address of the first
element of the array.  To specify a different element as the location for
your pointer, you must use the second form, and specify the array bounds
as you require.
-- 
D. Chadwick Gibbons, chad@lakesys.lakesys.com, ...!uunet!marque!lakesys!chad

davidsen@sungod.crd.ge.com (William Davidsen) (06/13/89)

|From: dooley@helios.toronto.edu (Kevin Dooley)
|Subject: array of pointers to functions
|Message-ID: <822@helios.toronto.edu>
|Date: 12 Jun 89 16:40:18 GMT
|Organization: University of Toronto Physics/Astronomy/CITA Computing Consortium

|I had a clever idea last night for a completely general routine to
|numerically solve a system of N coupled first order differential
|equations simultaneously using a Runge-Kutta algorithm.  The only
|way I can think of to conveniently pass an unspecified number of
|pointers to functions is to construct an array of pointers to the
|individual functions.  Imagine my alarm at discovering that this
|is not legal.  Why not?  Can anybody help me out with this little
|puzzle?

|From: maart@cs.vu.nl (Maarten Litmaath)
|Subject: address of function
|Message-ID: <2700@solo8.cs.vu.nl>
|Date: 6 Jun 89 17:37:09 GMT
|Organization: V.U. Informatica, Amsterdam, the Netherlands

|
|Why weren't function pointers handled the way below?
|
|	int	foo(), (*bar)() = &foo;

The following seem to work portably, and would satisfy the two questions
aboue.

/* function and pointer to it */
int foo(), (*bar)() = foo;		/* bar is pointer to foo */

/* vector of pointers to proc */
int curley(),
    larry(),
    moe();
int (*procvect[])() = { curley, larry, moe };

demo() {
  int k;
  for (k=0; k < 3; ++k)
    (*procvect[k])(k);
}


Sure hope this helps you guys. I may have misunderstood the questions,
of course.
	bill davidsen		(davidsen@crdos1.crd.GE.COM)
  {uunet | philabs}!crdgw1!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -me

diamond@diamond.csl.sony.junet (Norman Diamond) (06/14/89)

in answer to someone's question:

>> ... and does ANSI permit the following ?
>>	int	this[100], *that = &this;

In article <1817@auspex.auspex.com> guy@auspex.auspex.com (Guy Harris) writes:

>No.  It does permit
>	int	this[100], (*that)[100] = &this;
>since "&this" is a pointer to "this", and "this" is an array of 100
>"int"s, so "&this" is a pointer to an array of 100 "int"s (not a pointer
>to a single "int"

Oh I'm so glad ANSI is standardizing existing practices instead of
inventing new RESTRICTIONS.  This rule won't break much existing,
FORMERLY UNBROKEN source code, now will it?  :-S  (sarcasm)

Could one also do it in this way?
	int	this[100], *that = (int *)&this;
or maybe in this way?
	int	this[100], *that = (void *)&this;

i.e.:  when a cast implies an assignment to an anonymous temporary, it
becomes a non-lvalue -- ok; but does it also become a non-constant?

--
Norman Diamond, Sony Computer Science Lab (diamond%csl.sony.co.jp@relay.cs.net)
 The above opinions are my own.  However, if you see this at Waterloo, Stanford,
 or Anterior, then their administrators must have approved of these opinions.

karl@haddock.ima.isc.com (Karl Heuer) (06/15/89)

As has already been pointed out, my previous article in this thread had a
typo, reversing the names "this" and "foo" in the last paragraph.  I guess
I should have followed my earlier hunch and renamed the variables, thus:

|	int  a[100], (*pa)[100] = &a;
|is analogous to
|	int  f(void), (*pf)(void) = &f;
|This particular symmetry holds only if the explicit "&" is used.  Writing
|"f" without the ampersand yields the same as "&f", but writing "a"
|without the ampersand yields "&a[0]", which is not the same as "&a".
|(Though they will compare equal if brought to a common type.)

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

karl@haddock.ima.isc.com (Karl Heuer) (06/16/89)

In article <10361@socslgw.csl.sony.JUNET> diamond@csl.sony.junet (Norman Diamond) writes:
>In article <1817@auspex.auspex.com> guy@auspex.auspex.com (Guy Harris) writes:
>>["int this[100], *that = &this;" is not legal ANSI C]
>
>Oh I'm so glad ANSI is standardizing existing practices instead of
>inventing new RESTRICTIONS.  This rule won't break much existing,
>FORMERLY UNBROKEN source code, now will it?  :-S  (sarcasm)

No, it won't break any correct code, and it removes a restriction rather than
adding one.  Pre-ANSI C did not allow one to apply "&" to an array (see K&R1,
p. 94, next to last paragraph).  Perhaps you're thinking of the "feature" that
certain compilers flag this as a warning only, and ignore the "&".

>Could one also do it in this way?
>	int	this[100], *that = (int *)&this;
>	int	this[100], *that = (void *)&this;

I suppose that would work, but why don't you just write "that = &this[0]" (or
even "that = this"), if that's your intent?

>i.e.:  when a cast implies an assignment to an anonymous temporary, it
>becomes a non-lvalue -- ok; but does it also become a non-constant?

I can't think of any context in which the language cares whether an rvalue is
a "constant" or not.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

gwyn@smoke.BRL.MIL (Doug Gwyn) (06/17/89)

In article <10361@socslgw.csl.sony.JUNET> diamond@csl.sony.junet (Norman Diamond) writes:
>>> ... and does ANSI permit the following ?
>>>	int	this[100], *that = &this;
>In article <1817@auspex.auspex.com> guy@auspex.auspex.com (Guy Harris) writes:
>>No.  It does permit
>>	int	this[100], (*that)[100] = &this;
>Oh I'm so glad ANSI is standardizing existing practices instead of
>inventing new RESTRICTIONS.  This rule won't break much existing,
>FORMERLY UNBROKEN source code, now will it?  :-S  (sarcasm)

The (proposed) Standard does not in this regard (&array_name) break
existing correct code.  The base document, K&R1 Appendix A, quite
clearly constrains & to be applied to an lvalue and states that an
array identifier is not an lvalue expression.  The Standard has
actually extended the language in this regard, not restricted it.

The fact that some old compilers were sloppy and permitted an & to
be applied to an array identifier (usually as a no-op) is irrelevant
since it was not something a programmer could legitimately rely on.

karl@haddock.ima.isc.com (Karl Heuer) (06/20/89)

>I can't think of any context in which the language cares whether an rvalue is
>a "constant" or not.

I must have been asleep when I wrote that.  (Actually, I misunderstood the
terminology as being yet another manifestation of the misbelief that "an array
is just a constant pointer", and failed to note that it really was relevant to
the question.)

Of course the language does care about constant expressions; they specify the
width of a bitfield, the value of an enumeration constant, the size of an
array, the label of a |case| statement, the conditional of a preprocessor #if,
and (in the example under discussion) the initializer for an object of static
storage duration.

The question was whether a cast is permitted in a constant expression.  The
answer is "Yes, but only from arithmetic types to integral types" in the first
four cases above (integral constant expressions); "No, not at all" in the case
of a preprocessor #if.  For initializers, the language seems to accept
anything that's well-defined, including pointer-to-pointer casts.

>>	int	this[100], *that = (int *)&this;

So this is indeed legal (though, as I said before, writing it as "&this[0]"
eliminates the need for the cast, and is almost certainly clearer).

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint