By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,538 Members | 959 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,538 IT Pros & Developers. It's quick & easy.

Re: function name as function pointer

P: n/a
Stephen Sprunk said:

<snip>
A function name decays to a pointer-to-function in most contexts just
like an array of foo decays to a pointer-to-foo in most contexts.
Almost.

A function name *is* a pointer-to-function. You can do two things with it -
copy it (assign its value to an object of function pointer type, with a
cast if necessary but preferably to one of the /right/ function pointer
type!), or call it (by dereferencing it and supplying a (possibly empty)
parameter list. There is no "decay" involved.

As a special ANSI (and thus ISO) dispensation, you can omit the dereference
operator. Thus, given:

int (*foo)(int) = isspace;

this is legal:

int x = (*foo)('A')';

and so is this:

int y = foo('A');

and so, would you believe, is this:

int z = (*****foo)('A');

This is very UNlike the rule for arrays. Given char bar[32]; the identifier
bar does indeed decay to a pointer to its first element when used in a
value context. Nevertheless, you can take its address - &bar - and this
gives you, not a char *, but a char (*)[32]. You can dereference it - *bar
- but this gives you a char, not a char *. And you can hand it to sizeof,
which you can't do with function pointers.

(This is partly a minor rebuttal to Stephen's point, but mostly an
expansion of it - I know Stephen knows this stuff.)

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 9 '08 #1
Share this Question
Share on Google+
10 Replies


P: n/a
On Tue, 09 Sep 2008 16:58:23 +0000, Richard Heathfield wrote:
Stephen Sprunk said:

<snip>
>A function name decays to a pointer-to-function in most contexts just
like an array of foo decays to a pointer-to-foo in most contexts.

Almost.

A function name *is* a pointer-to-function.
No, it's not. The name of a function, when used in an expression, has
function type. Except when it's the operand of unary & or sizeof, it is
converted to pointer-to-function.
This is very UNlike the rule for arrays. Given char bar[32]; the
identifier bar does indeed decay to a pointer to its first element when
used in a value context.
Similar to how a function decays to a function pointer?
Nevertheless, you can take its address - &bar -
and this gives you, not a char *, but a char (*)[32].
Similar to how you can take an int(void)'s address, and this gives you not
an int, but an int(*)(void)?
You can
dereference it - *bar - but this gives you a char, not a char *.
No, you can't dereference an array, but you can dereference a pointer to
an array's initial element. What would be the syntax for the former, if it
were valid, is actually the syntax for the latter.

int x[2];
*x;

The operand of unary * has type int *. It is the result of the decay of an
array to a pointer.
And you
can hand it to sizeof, which you can't do with function pointers.
Which you can do with function pointers, but which you can't do with
functions. However, the fact that you cannot take a function's size has
nothing to do with its decay to a pointer to a function.
Sep 9 '08 #2

P: n/a
Richard Heathfield <rj*@see.sig.invalidwrites:
Stephen Sprunk said:

<snip>
>A function name decays to a pointer-to-function in most contexts just
like an array of foo decays to a pointer-to-foo in most contexts.

Almost.

A function name *is* a pointer-to-function. You can do two things with it -
copy it (assign its value to an object of function pointer type, with a
cast if necessary but preferably to one of the /right/ function pointer
type!), or call it (by dereferencing it and supplying a (possibly empty)
parameter list. There is no "decay" involved.
[...]

Stephen is right, and you are mistaken.

C99 6.3.2.1p4:

A _function designator_ is an expression that has function
type. Except when it is the operand of the sizeof operator or the
unary & operator, a function designator with type "function
returning _type_" is converted to an expression that has type
"pointer to function returning _type_".

with a footnote:

Because this conversion does not occur, the operand of the sizeof
operator remains a function designator and violates the constraint
in 6.5.3.4.

(I think C90 has similar wording, but my copy is messed up at the
moment.)

A function name is one example of an expression that has function
type. The value of that expression, in most contexts, is converted to
(i.e., "decays" to) a pointer to the function.
As a special ANSI (and thus ISO) dispensation, you can omit the dereference
operator. Thus, given:

int (*foo)(int) = isspace;

this is legal:
Right, because the expression ``isspace'' is implicitly converted from
a function type to a pointer-to-function-type.
int x = (*foo)('A')';
foo is of pointer-to-function type. It's dereferenced, yielding a
value of functiont type, which is immediately converted to
pointer-to-function type -- which is just what's needed for the
function call "operator" (the standard doesn't call it an operator).
and so is this:

int y = foo('A');
Right, no conversion is necessary.
and so, would you believe, is this:

int z = (*****foo)('A');
*foo, as above, is of pointer-to-function type. **foo is of function
type, and decays to pointer-to-function type. ***foo is of function
type, and decays to pointer-to-function type. And so on.
This is very UNlike the rule for arrays. Given char bar[32]; the identifier
bar does indeed decay to a pointer to its first element when used in a
value context. Nevertheless, you can take its address - &bar - and this
gives you, not a char *, but a char (*)[32]. You can dereference it - *bar
- but this gives you a char, not a char *. And you can hand it to sizeof,
which you can't do with function pointers.
It's almost exactly like the rule for arrays, except that a function
decays to a pointer to the function itself whereas an array name
decays to a pointer to the array's first element. Given
void func(void);
``func'' decays to a pointer to the function when used in a value
context. You can take its address, ``&func'' (this a case where the
decay doesn't happen), and this gives you the address of the function.
You can dereference it, ``*func''; this gives an expression of
function type that immediately decays back to a pointer-to-function.
You can't do ``sizeof func'' but only because the constraint in C99
6.5.3.4p1 specifically disallows it.
(This is partly a minor rebuttal to Stephen's point, but mostly an
expansion of it - I know Stephen knows this stuff.)
I hope not. 8-)}

It's likely that the rules you describe yield identical results to the
rules in the standard, but they're not what the standard says.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 9 '08 #3

P: n/a
Keith Thompson said:
Richard Heathfield <rj*@see.sig.invalidwrites:
<snip>
>(This is partly a minor rebuttal to Stephen's point, but mostly an
expansion of it - I know Stephen knows this stuff.)

I hope not. 8-)}

It's likely that the rules you describe yield identical results to the
rules in the standard, but they're not what the standard says.
WELL! I sit corrected. Apologies to Stephen for an incorrect "correction".

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 9 '08 #4

P: n/a
On Sep 9, 10:16 pm, Harald van Dk <true...@gmail.comwrote:
On Tue, 09 Sep 2008 16:58:23 +0000, Richard Heathfield wrote:
Stephen Sprunk said:
<snip>
A function name decays to a pointer-to-function in most contexts just
like an array of foo decays to a pointer-to-foo in most contexts.
Almost.
A function name *is* a pointer-to-function.

No, it's not. The name of a function, when used in an expression, has
function type. Except when it's the operand of unary & or sizeof, it is
converted to pointer-to-function.
This is very UNlike the rule for arrays. Given char bar[32]; the
identifier bar does indeed decay to a pointer to its first element when
used in a value context.

Similar to how a function decays to a function pointer?
Nevertheless, you can take its address - &bar -
and this gives you, not a char *, but a char (*)[32].

Similar to how you can take an int(void)'s address, and this gives you not
an int, but an int(*)(void)?
You can
dereference it - *bar - but this gives you a char, not a char *.

No, you can't dereference an array, but you can dereference a pointer to
an array's initial element. What would be the syntax for the former, if it
were valid, is actually the syntax for the latter.

int x[2];
*x;

The operand of unary * has type int *. It is the result of the decay of an
array to a pointer.
And you
can hand it to sizeof, which you can't do with function pointers.
I was able to do the sizeof with function pointer. There should be no
problem with it.

>
Which you can do with function pointers, but which you can't do with
functions. However, the fact that you cannot take a function's size has
nothing to do with its decay to a pointer to a function.
Sep 9 '08 #5

P: n/a
Richard Heathfield wrote:
Stephen Sprunk said:
>A function name decays to a pointer-to-function in most contexts just
like an array of foo decays to a pointer-to-foo in most contexts.

Almost.

A function name *is* a pointer-to-function. You can do two things with it -
copy it (assign its value to an object of function pointer type, with a
cast if necessary but preferably to one of the /right/ function pointer
type!), or call it (by dereferencing it and supplying a (possibly empty)
parameter list. There is no "decay" involved.
The problem with your explanation is that "&func" gives a
pointer-to-function. If "func" itself were a pointer-to-function,
"&func" would give a pointer-to-pointer-to-function. In reality, "func"
decays to pointer-to-function except in certain cases, e.g. when it's
the object of the unary & -- just line an array.

(Or, at least, it _acts_ like that's what happens.)
This is very UNlike the rule for arrays. Given char bar[32]; the identifier
bar does indeed decay to a pointer to its first element when used in a
value context. Nevertheless, you can take its address - &bar - and this
gives you, not a char *, but a char (*)[32]. You can dereference it - *bar
- but this gives you a char, not a char *.
I may be unclear on the details there. If "*arr" gives you a char, then
it stands to reason "arr" has decayed to a pointer-to-char.
And you can hand it to sizeof, which you can't do with function pointers.
Right; that would be one of the exceptions to the decay. If "func" were
a pointer-to-function, then "sizeof func" would give the size of a
pointer-to-function. Without the decay, it would need to give the size
of the function itself, which is undefined since functions aren't objects.
(This is partly a minor rebuttal to Stephen's point, but mostly an
expansion of it - I know Stephen knows this stuff.)
However, I sometimes get sloppy in my explanations due to not
understanding the fine distinctions of jargon. I welcome corrections
from the pedants.

S
Sep 9 '08 #6

P: n/a
sh******@gmail.com writes:
[...]
>On Tue, 09 Sep 2008 16:58:23 +0000, Richard Heathfield wrote:
[...]
And you
can hand it to sizeof, which you can't do with function pointers.

I was able to do the sizeof with function pointer. There should be no
problem with it.
[...]

Right, you can apply sizeof to an expression of pointer-to-function
type, such as the name of an object of pointer-to-function type.

The point is that a function name does not "decay" to a pointer when
it's the operand of a unary sizeof or "*" operator. For example,
given a function named "func", the expression `sizeof func'' doesn't
yield the size of a pointer to the function; instead, it's a
constraint violation. (Normally ``func'', after the decay, is of
pointer-to-function type, but the decay doesn't occur in this
context.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 9 '08 #7

P: n/a
Keith Thompson <ks***@mib.orgwrites:
[...]
C99 6.3.2.1p4:

A _function designator_ is an expression that has function
type. Except when it is the operand of the sizeof operator or the
unary & operator, a function designator with type "function
returning _type_" is converted to an expression that has type
"pointer to function returning _type_".

with a footnote:

Because this conversion does not occur, the operand of the sizeof
operator remains a function designator and violates the constraint
in 6.5.3.4.

(I think C90 has similar wording, but my copy is messed up at the
moment.)
[..]

The wording in C90 is identical (apart from the section reference in
the footnote).

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 9 '08 #8

P: n/a
Keith Thompson <ks***@mib.orgwrites:

[...]
Right, you can apply sizeof to an expression of pointer-to-function
type, such as the name of an object of pointer-to-function type.

The point is that a function name does not "decay" to a pointer when
it's the operand of a unary sizeof or "*" operator.
Of course, what you meant to say is that a function name isn't
converted to pointer-to-function when it's the operand of
a unary "&" operator.
Sep 9 '08 #9

P: n/a
Tim Rentsch <tx*@alumnus.caltech.eduwrites:
Keith Thompson <ks***@mib.orgwrites:

[...]
>Right, you can apply sizeof to an expression of pointer-to-function
type, such as the name of an object of pointer-to-function type.

The point is that a function name does not "decay" to a pointer when
it's the operand of a unary sizeof or "*" operator.

Of course, what you meant to say is that a function name isn't
converted to pointer-to-function when it's the operand of
a unary "&" operator.
Yes, thanks. (D'oh!)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 9 '08 #10

P: n/a
On Tue, 09 Sep 2008 10:27:14 -0700, Keith Thompson <ks***@mib.org>
wrote:
<snip>
Stephen is right, and you are mistaken.

C99 6.3.2.1p4: <snip>
int x = (*foo)('A')';

foo is of pointer-to-function type. It's dereferenced, yielding a
value of functiont type, which is immediately converted to
pointer-to-function type -- which is just what's needed for the
function call "operator" (the standard doesn't call it an operator).
<snip correct semantics and examples>

Nit: it isn't explicitly named an operator, but it is placed within
6.5.2 (formerly 6.3.2) Postfix Operators. In C90 it is indexed as
'function-call operator' once (under parens) and just 'function call'
once; in C99 these are both (consistently) 'function-call operator'.
Although neither of these is AFAICS officially a defined term (i.e.
italicized) so the distinction doesn't really matter.

C also classifies as operators member selection, (array) subscripting,
cast (for type conversion), and (C99 only) compound literals. In
(most?) other HLLs at least the first two, sometimes third, and fourth
if applicable, are considered (syntactically) forms of primary or
other specific NT, rather than expressions containing operators.
Array subscripting in C, and B and BCPL before it, is truly 'just' an
operation and hence reasonably an operator, and into early (very
prestandard) C member selection was very close; function call is
similarly partly operatorish: its left operand is 'just' a (possibly
computed) (r)value but its right operand is special. I think compound
literals were simply shoehorned in there for convenience, much as
typedef is a storage-class syntactically but not semantically.

Similarly, C calls assignment an operator/operation (actually a series
of them e.g. = *= ++ etc.), and lets it be nested; most(?) other HLLs
call it a form(s) of statement, thus allowing it only at top level
(or implicitly in by-value call and return and initialization).
C does call a parenthesized (sub)expression a form of primary.
OT&FWIW, C++ calls :: an operator, the 'scope resolution operator',
even though both/all its operands are compiletime identifiers.

- formerly david.thompson1 || achar(64) || worldnet.att.net
Sep 22 '08 #11

This discussion thread is closed

Replies have been disabled for this discussion.