function name as function pointer

S

sh.vipin

Below is the outcome of a source code and code itself in the same
order. We know that every function name behaves like a pointer to
function also. But at the same time, based on result, function name
also has the same value as its address(1st and 3rd line in result are
same).

i.e. it seems that for any function
int fun(){
.....
}

following holds true always.
&fun == fun

Otherwise, i think there is no way
that (**************fun)() , fun() and (*fun)() could behave in same
way.

My queries are
1. Is it an ANSI C Standard or just a compilers' implementation
methodology.
2. I believe that *fun should give the address of a location from
where the code for function starts. It should be in code segment. Then
how come a variable "fun" (i.e. function name itself ) is also having
an address which lies in code segment.




------------RESULT-------------
Address OF 4198728
Address OF 4202500
Address IN 4198728
Address IN 4198728
I watched "A Wednesday" this friday.
I watched "A Wednesday" this friday.
-------------------------


/* CODE */
int gef(){
printf("\n I watched \"A Wednesday\" this firday.");
}
int (*z)() =gef;
int main (int argc, char *argv[]){
printf("\n Address OF %u ",&gef);
printf("\n Address OF %u ",&z);

printf("\n Address IN %u ",gef);
printf("\n Address IN %u ",z);

(****z)();
(*****gef)();

return 0;
}


-vipin
 
S

Stephen Sprunk

Below is the outcome of a source code and code itself in the same
order. We know that every function name behaves like a pointer to
function also. But at the same time, based on result, function name
also has the same value as its address(1st and 3rd line in result are
same). ....
My queries are
1. Is it an ANSI C Standard or just a compilers' implementation
methodology.

It's in the standard (ANSI or ISO, take your pick).
2. I believe that *fun should give the address of a location from
where the code for function starts. It should be in code segment. Then
how come a variable "fun" (i.e. function name itself ) is also having
an address which lies in code segment.

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.

S
 
H

Harald van Dijk

Stephen Sprunk said:



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.
 
K

Keith Thompson

Richard Heathfield said:
Stephen Sprunk said:



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. :cool:}

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.
 
K

Keith Thompson

Below is the outcome of a source code and code itself in the same
order. We know that every function name behaves like a pointer to
function also.

In most contexts, yes, a function name is converted to a pointer to
the function.
But at the same time, based on result, function name
also has the same value as its address(1st and 3rd line in result are
same).

Right. That's what "address" means in C. A pointer to foo is exactly
the same as the address of foo.

[...]
/* CODE */
int gef(){
printf("\n I watched \"A Wednesday\" this firday.");
}
int (*z)() =gef;
int main (int argc, char *argv[]){
printf("\n Address OF %u ",&gef);
printf("\n Address OF %u ",&z);

printf("\n Address IN %u ",gef);
printf("\n Address IN %u ",z);

(****z)();
(*****gef)();

return 0;
}

printf's "%u" format is for printing values of type unsigned int (in
decimal). It's not for printing pointer / address values. Apparently
it happens to "work" on your system, but it's not guaranteed.

To print most pointer values, you should use the "%p" format with a
conversion to void*:

int i;
printf("Address of i is %p\n", (void*)&i);

But there is no portable way to print a pointer-to-function value,
other than by decomposing its representation into an array of bytes.

A quick-and-dirty way to *try* to print a function pointer is to
convert it to void* and use %p:

int gef() { ... }
...
printf("&gef = %p\n", (void*)&gef);

It's still not guaranteed to work, but it's (probably) more likely to
give meaningful results than using "%u".
 
S

sh.vipin

Stephen Sprunk said:


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.
 
S

sh.vipin

Below is the outcome of a source code and code itself in the same
order. We know that every function name behaves like a pointer to
function also.

In most contexts, yes, a function name is converted to a pointer to
the function.
               But at the same time, based on result, function name
also has the same value as its address(1st and 3rd line in result are
same).

Right.  That's what "address" means in C.  A pointer to foo is exactly
the same as the address of foo.

[...]




/* CODE */
int gef(){
   printf("\n I watched \"A Wednesday\" this firday.");
}
int (*z)() =gef;
int main (int argc, char *argv[]){
   printf("\n Address OF %u ",&gef);
   printf("\n Address OF %u ",&z);
   printf("\n Address IN %u ",gef);
   printf("\n Address IN %u ",z);
   (****z)();
   (*****gef)();
   return 0;
}

printf's "%u" format is for printing values of type unsigned int (in
decimal).  It's not for printing pointer / address values.  Apparently
it happens to "work" on your system, but it's not guaranteed.

To print most pointer values, you should use the "%p" format with a
conversion to void*:

    int i;
    printf("Address of i is %p\n", (void*)&i);

But there is no portable way to print a pointer-to-function value,
other than by decomposing its representation into an array of bytes.

A quick-and-dirty way to *try* to print a function pointer is to
convert it to void* and use %p:

    int gef() { ... }
    ...
    printf("&gef = %p\n", (void*)&gef);

It's still not guaranteed to work, but it's (probably) more likely to
give meaningful results than using "%u".

--
Keith Thompson (The_Other_Keith) (e-mail address removed)  <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"- Hide quoted text -

- Show quoted text -

Thanks Keith for correcting me for improper usage of %u.
However there is one more experiment I tried.

After adding following line in code,

printf("\n %d %d %d %d",
sizeof(int*),
sizeof(float*),
sizeof(char *),
sizeof(gef));

I got the following line added to the result.

4 4 4 1

Why the sizeof(gef) is being shown as "1" ?
I am using gcc compiler.
 
S

Stephen Sprunk

Richard said:
Stephen Sprunk said:

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
 
S

Stephen Sprunk

....
After adding following line in code,

printf("\n %d %d %d %d",
sizeof(int*),
sizeof(float*),
sizeof(char *),
sizeof(gef));

I got the following line added to the result.

4 4 4 1

Why the sizeof(gef) is being shown as "1" ?
I am using gcc compiler.

In the particular instances of unary & or sizeof, "gef" does _not_ decay
to pointer-to-function. sizeof is only defined for objects, not
functions (e.g. gef). Apparently, GCC's authors decided to use the
value "1" when asked for the size of a function rather than rejecting
your program or some other behavior.

However, sizeof(&gef) is defined, since a pointer-to-function is an
object. This sidesteps the issue of functions not decaying to
pointer-to-function when passed to sizeof.

S
 
K

Keith Thompson

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.)
 
K

Keith Thompson

Keith Thompson said:
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).
 
K

Keith Thompson

Thanks Keith for correcting me for improper usage of %u.
However there is one more experiment I tried.

After adding following line in code,

printf("\n %d %d %d %d",
sizeof(int*),
sizeof(float*),
sizeof(char *),
sizeof(gef));

I got the following line added to the result.

4 4 4 1

Why the sizeof(gef) is being shown as "1" ?

Because ...
I am using gcc compiler.

In standard C, applying sizeof to a function name is a constraint
violation. With the right set of options, you can get gcc to warn you
about it.

gcc has an extension that allows pointer arithmetic on pointers to
void and on pointers to functions. In both cases, this is implemented
by pretending that the size of the pointed-to type is 1 (yes,
sizeof(void) == 1 under gcc). See the gcc documentation or ask in
gnu.gcc.help for more information.

A couple more things:

Please trim quoted material when you post a followup. It's rarely
necessary to quote the entire parent article, and hardly ever
necessary to quote the signature. Keep just enough so your followup
makes sense on its own. (But be sure to leave the attribution lines
in place for any quoted text.0

The "%d" format is used for values of type int. The sizeof operator
yields a result of type size_t. This happened to work on your system,
but in general you should either convert the result to some type for
which printf has a format, or use the (C99-specific) "%zu" format.

printf("sizeof(int*) = %d\n", sizeof(int*)); /* WRONG */
printf("sizeof(int*) = %lu\n",
(unsigned long)sizeof(int*)); /* OK */
printf("sizeof(int*) = %zu\n",
sizeof(int*)); /* OK *if* your implementation supports it */
 
T

Tim Rentsch

[...]
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.
 
K

Keith Thompson

Tim Rentsch said:
[...]
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!)
 
V

vippstar

Yes, the size_t nonsense even wrecks printf().
It is a destroying ball that works its way through the entirety of the C
language.

I disagree, it's not nonsense. I think it's very convenient to have a
type with such guarantees.
I just think it was a mistake to not have a specifier in C89 for
size_t.
(Of course, C89's largest integer was guaranteed to be unsigned long,
not uintmax_t as introduced in C99, so you can use that)
I think you know all that, so what are you talking about?
 
D

David Thompson

Stephen is right, and you are mistaken.



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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,992
Messages
2,570,220
Members
46,807
Latest member
ryef

Latest Threads

Top