469,934 Members | 1,941 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,934 developers. It's quick & easy.

function pointers as function parameters

I am experimenting with function pointers. Unfortunately, my C book has
nothing on function pointers as function parameters. I want to pass a
pointer to ff() to f() with the result that f() prints the return value
of ff(). The code below seems to work, but I would appreciate your
comments. Have I got it right? Does the function name "decay" to a pointer?
#include <stdio.h>
/* declares a function which takes an argument
that is a pointer to a function returning an int */
void f(int (*fptr)());
/* function returning an int */
int ff(void);

int main(void)
{
f(ff); /* pass the address of ff to f */

return 0;
}

void f(int (*fptr)())
{
int a;
a = (*fptr)(); /* deref the func pointer */
printf("%d\n", a);
return;
}

int ff(void)
{
return 2345;
}
Nov 14 '05 #1
27 2240


Marlene Stebbins wrote:
I am experimenting with function pointers. Unfortunately, my C book has
nothing on function pointers as function parameters. I want to pass a
pointer to ff() to f() with the result that f() prints the return value
of ff(). The code below seems to work, but I would appreciate your
comments. Have I got it right? Does the function name "decay" to a pointer?
It might be simpler to say that the function name "is"
a pointer to the function, since there is no context in
which it does anything other than "decay."

Your code is correct (as far as I can see), but there
are a few opportunities for stylistic improvement:
#include <stdio.h>
/* declares a function which takes an argument
that is a pointer to a function returning an int */
void f(int (*fptr)());
You know more about the pointed-to function than the
type of its returned value: specifically, you know that
it takes no arguments. (How do you know this? Because
you supply no arguments when you call it.) On the general
principle that it's best to tell the compiler everything
you know, write the declaration as

void f(int (*fptr)(void));

This way, the compiler will protest if you inadvertently
try to call the pointed-to function with arguments. If
you do in fact want to pass arguments, say so:

void f2(int (*fptr)(double, int, const char*));
/* function returning an int */
int ff(void);

int main(void)
{
f(ff); /* pass the address of ff to f */
Here's where ff "decays."
return 0;
}

void f(int (*fptr)())
If you've provided a prototype as suggested above,
you should also do so here.
{
int a;
a = (*fptr)(); /* deref the func pointer */
This can also be written `a = fptr();' without the
parentheses and the asterisk. Some people prefer to write
the call as you've done it, saying that it draws attention
to the fact that a function pointer variable (rather than
a function identifier) is being used. I personally don't
buy that argument, noting that

(*printf)("Hello, world!\n");

is equally legitimate and (IMHO) equally silly. However,
de gustibus non disputandum est (Latin for "There's just
no arguing with Gus").
printf("%d\n", a);
return;
}

int ff(void)
{
return 2345;
}


--
Er*********@sun.com

Nov 14 '05 #2
Eric Sosman wrote:

Marlene Stebbins wrote:
I am experimenting with function pointers.
Unfortunately, my C book has
nothing on function pointers as function parameters.
I want to pass a
pointer to ff() to f() with the result that f()
prints the return value
of ff(). The code below seems to work, but I would appreciate your
comments. Have I got it right?
Does the function name "decay" to a pointer?


It might be simpler to say that the function name "is"
a pointer to the function, since there is no context in
which it does anything other than "decay."


The function name remains an expression of a function type
when it is an operand of the address operator.
You can force a non macro invocation of a standard library
function by calling it like
(&putchar)('\n');
which wouldn't make sense if putchar were a pointer.
If a function name were a pointer expression,
then it would be a valid operand of the sizeof operator.
For those two reasons,
I would not say that a function name is a pointer.

--
pete
Nov 14 '05 #3
Marlene Stebbins wrote on 02/05/05 :
#include <stdio.h>
/* declares a function which takes an argument
that is a pointer to a function returning an int */
void f(int (*fptr)());
/* function returning an int */
int ff(void);

int main(void)
{
f(ff); /* pass the address of ff to f */

return 0;
}

void f(int (*fptr)())
{
int a;
a = (*fptr)(); /* deref the func pointer */
printf("%d\n", a);
return;
}

int ff(void)
{
return 2345;
}


You've got it (jist add 'void' into the () and it's all fine). Now, try
the Simple Way:

#include <stdio.h>

typedef int F (void);

static int ff (void)
{
return 2345;
}

static void f (F * pf)
{
/* deref the func pointer */
int a = pf ();

printf ("%d\n", a);
return;
}

int main (void)
{
/* pass the address of ff to f */
f (ff);

return 0;
}

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Clearly your code does not meet the original spec."
"You are sentenced to 30 lashes with a wet noodle."
-- Jerry Coffin in a.l.c.c++

Nov 14 '05 #4
Eric Sosman <er*********@sun.com> writes:
Marlene Stebbins wrote:
I am experimenting with function pointers. Unfortunately, my C book has
nothing on function pointers as function parameters. I want to pass a
pointer to ff() to f() with the result that f() prints the return value
of ff(). The code below seems to work, but I would appreciate your
comments. Have I got it right? Does the function name "decay" to a pointer?
It might be simpler to say that the function name "is"
a pointer to the function, since there is no context in
which it does anything other than "decay."


Almost. A function name decays (is implicitly converted) to a pointer
in most contexts. The exceptions are when it's the operand of a unary "&"
(&ff yields a pointer-to-function, not a pointer-to-pointer-to-function),
and when it's the operand of sizeof (sizeof ff is illegal; if it
decayed in that context it would yield the size of a function
pointer).

[snip] This can also be written `a = fptr();' without the
parentheses and the asterisk. Some people prefer to write
the call as you've done it, saying that it draws attention
to the fact that a function pointer variable (rather than
a function identifier) is being used. I personally don't
buy that argument, noting that

(*printf)("Hello, world!\n");

is equally legitimate and (IMHO) equally silly. However,
de gustibus non disputandum est (Latin for "There's just
no arguing with Gus").


Note that
(*printf)("Hello, world!\n");
isn't exactly equivalent to
printf("Hello, world!\n");
since the latter could invoke a macro. That's a special rule for
functions declared in standard headers. But if you want to avoid the
macro and call the actual function, you can just use parentheses:

(printf)("Hello, world!\n");

Hmm. Actually, since printf() takes a variable number of arguments,
implementing it as a macro is not possible in C90; I'm not sure
whether it's possible in C99. But I digress.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #5
On Mon, 02 May 2005 18:59:12 +0000, pete wrote:
Eric Sosman wrote:

Marlene Stebbins wrote:
> I am experimenting with function pointers.
> Unfortunately, my C book has
> nothing on function pointers as function parameters.
> I want to pass a
> pointer to ff() to f() with the result that f()
> prints the return value
> of ff(). The code below seems to work, but I would appreciate your
> comments. Have I got it right?
> Does the function name "decay" to a pointer?
It might be simpler to say that the function name "is"
a pointer to the function, since there is no context in
which it does anything other than "decay."


The function name remains an expression of a function type
when it is an operand of the address operator.
You can force a non macro invocation of a standard library
function by calling it like
(&putchar)('\n');


That's true although in practice it tends to be written as

(putchar)('\n');
which wouldn't make sense if putchar were a pointer.
But, yes, your form makes this point.
If a function name were a pointer expression,
then it would be a valid operand of the sizeof operator.
For those two reasons,
I would not say that a function name is a pointer.


It is a very similar argument to that for array names. Array names have
array type but in many cases an array "value" is given as a pointer to the
array's first element, so in those cases it appears to be a pointer. But
it isn't and as with functions &array and sizeof array show its true
nature.

Lawrence
Nov 14 '05 #6
Lawrence Kirby wrote:

On Mon, 02 May 2005 18:59:12 +0000, pete wrote:
Eric Sosman wrote:
It might be simpler to say that the function name "is"
a pointer to the function, since there is no context in
which it does anything other than "decay."


The function name remains an expression of a function type
when it is an operand of the address operator.
You can force a non macro invocation of a standard library
function by calling it like
(&putchar)('\n');


That's true although in practice it tends to be written as

(putchar)('\n');
which wouldn't make sense if putchar were a pointer.


But, yes, your form makes this point.
If a function name were a pointer expression,
then it would be a valid operand of the sizeof operator.
For those two reasons,
I would not say that a function name is a pointer.


It is a very similar argument to that for array names.
Array names have array type but in many cases an array "value"
is given as a pointer to the array's first element,
so in those cases it appears to be a pointer.
But it isn't and as with functions &array
and sizeof array show its true nature.


I would agree with Eric Sosman's statement to the extent
that the only use of a value of an expression of a function type,
is that a pointer can be derived from it.

What constitutes the value of an array type, is more complicated.
The value of an array type (even an incomplete array type)
can be converted to a pointer.
The value of an array type can initialize an array.
char array[] = "";
The value of an array type structure member,
is a byte by byte copy when the structure
is an operand of the assignment operator.

--
pete
Nov 14 '05 #7

In article <ln************@nuthaus.mib.org>, Keith Thompson <ks***@mib.org> writes:
Eric Sosman <er*********@sun.com> writes:

It might be simpler to say that the function name "is"
a pointer to the function, since there is no context in
which it does anything other than "decay."


Almost. A function name decays (is implicitly converted) to a pointer
in most contexts. The exceptions are when it's the operand of a unary "&"
(&ff yields a pointer-to-function, not a pointer-to-pointer-to-function),
and when it's the operand of sizeof (sizeof ff is illegal; if it
decayed in that context it would yield the size of a function
pointer).


I was mulling over the hypothesis that the & and * operators, when
applied to function names, simply did nothing, but your last example
made me think of a possible counterexample. Is the following a
strictly conforming expression?

sizeof &main;

Or, if you prefer the full-program version:

#include <stdio.h>
int main(void) {
printf("%lu\n", (unsigned long) sizeof &main);
return 0;
}

If it is, aside from that, are there any other cases where the & and
* operators have any effect when applied to a function name?

--
Michael Wojcik mi************@microfocus.com

"We are facing a dire shortage of clowns," said Erickson, also known as
Jingles.
Nov 14 '05 #8


pete wrote:
Lawrence Kirby wrote:
On Mon, 02 May 2005 18:59:12 +0000, pete wrote:

Eric Sosman wrote:
It might be simpler to say that the function name "is"
a pointer to the function, since there is no context in
which it does anything other than "decay."

The function name remains an expression of a function type
when it is an operand of the address operator.
You can force a non macro invocation of a standard library
function by calling it like
(&putchar)('\n');


That's true although in practice it tends to be written as

(putchar)('\n');

which wouldn't make sense if putchar were a pointer.


But, yes, your form makes this point.

If a function name were a pointer expression,
then it would be a valid operand of the sizeof operator.
For those two reasons,
I would not say that a function name is a pointer.


It is a very similar argument to that for array names.
Array names have array type but in many cases an array "value"
is given as a pointer to the array's first element,
so in those cases it appears to be a pointer.
But it isn't and as with functions &array
and sizeof array show its true nature.

I would agree with Eric Sosman's statement to the extent
that the only use of a value of an expression of a function type,
is that a pointer can be derived from it.


Although it's flattering to learn that someone agrees with
me, it is also a bit embarrassing -- because I have come to
*dis*agree with myself ;-)

I said there was no context in which a function identifier
doesn't "decay" to a pointer to the function, but Keith
Thompson has convinced me I was wrong. Specifically:

- In the context `&func', the `func' part does not behave
like a pointer-to-function. If it did, the entire
expression would be pointer-to-pointer-to-function --
but, strangely enough, both `func' and `&func' (and
even `&&&&&&&func') are pointer-to-function.

- In the context `sizeof func', the `func' part does not
behave like a pointer-to-function. If it did, the
expression would evaluate to the size of a function
pointer, but in actuality the expression produces a
diagnostic.

The second point is debatable: since the context is not
valid C at all, its odd behavior doesn't matter. One might
equally well make arguments about the array-indexing operator
in the context `[4]"Hello"'; interesting things might be said,
but they'd have little to do with C. But even if one rejects
the second point, the first seems unassailable: Keith is right
and I was wrong, R-O-N-G, wrong.

--
Er*********@sun.com

Nov 14 '05 #9
Your code is good. Let me also point you to an article I wrote recently
involving the subject:

http://www-128.ibm.com/developerwork...-highfunc.html

Some of the code in there is non-standard C, but works for most
platforms most people deal with.

Jon
----
Learn to program using Linux assembly language
http://www.cafeshops.com/bartlettpublish.8640017
Nov 14 '05 #10
On Tue, 03 May 2005 10:57:05 -0400, Eric Sosman wrote:

....
I said there was no context in which a function identifier
doesn't "decay" to a pointer to the function, but Keith
Thompson has convinced me I was wrong. Specifically:

- In the context `&func', the `func' part does not behave
like a pointer-to-function. If it did, the entire
expression would be pointer-to-pointer-to-function --
but, strangely enough, both `func' and `&func' (and
even `&&&&&&&func') are pointer-to-function.


Using the && operator like this is a syntax error. But even
(& &func) is invalid because unary & requires an lvalue or function
designator as its operand, but it doesn't produce either as its result.

Lawrence

Nov 14 '05 #11
Eric Sosman <er*********@sun.com> writes:
[...]
Although it's flattering to learn that someone agrees with
me, it is also a bit embarrassing -- because I have come to
*dis*agree with myself ;-)

I said there was no context in which a function identifier
doesn't "decay" to a pointer to the function, but Keith
Thompson has convinced me I was wrong. Specifically:

- In the context `&func', the `func' part does not behave
like a pointer-to-function. If it did, the entire
expression would be pointer-to-pointer-to-function --
but, strangely enough, both `func' and `&func' (and
even `&&&&&&&func') are pointer-to-function.
As Lawrence Kirby pointed out, this is illegal because the "maximal
munch" rule turns this into three "&&" operators followed by an "&"
operator; once you fix that, it's still illegal because &func isn't a
lvalue. But you can have &func, func, *func, **func, *****func, and
*&*&*&*&func.
- In the context `sizeof func', the `func' part does not
behave like a pointer-to-function. If it did, then
expression would evaluate to the size of a function
pointer, but in actuality the expression produces a
diagnostic.

The second point is debatable: since the context is not
valid C at all, its odd behavior doesn't matter. One might
equally well make arguments about the array-indexing operator
in the context `[4]"Hello"'; interesting things might be said,
but they'd have little to do with C. But even if one rejects
the second point, the first seems unassailable: Keith is right
and I was wrong, R-O-N-G, wrong.


I hate to force you to disagree with yourself even further, but here's
what the standard says:

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(54) 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".

And footnote (54):

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.

6.5.3.4p1 says:

Constraints

The sizeof operator shall not be applied to an expression that has
function type or an incomplete type, to the parenthesized name of
such a type, or to an expression that designates a bit-field
member.

It seems a little convoluted to make an exception to the rule for the
operand of a sizeof operator, only to make it a constraint violation
in a different section of the standard, but I think this is actually
the most straightforward way to do it. The rule is similar to the
rule for arrays, except that it makes sense to apply sizeof to an
array value.

[4]"Hello", on the other hand, is a syntax error, not a constraint
violation. (And as you know, 4["Hello"] is perfectly legal.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #12
Michael Wojcik wrote:
sizeof &main;
That's the size of a pointer.
If it is, aside from that, are there any other cases where the & and
* operators have any effect when applied to a function name?


The * operator always converts the function type expression
to a pointer, prior to operating on it.

These are all valid function calls:

(putchar)('\n');
(&putchar)('\n');
(*putchar)('\n');

In the first one, the function type expression,
is converted to a pointer, by the function call operator.

The second one has no conversions.

In the third one, the * operator converts the function type
expression to a pointer, then operates on it,
the result is an expression of function type
which is converted to a pointer by the function call operator.

--
pete
Nov 14 '05 #13
Eric Sosman wrote:

pete wrote:
Lawrence Kirby wrote:
On Mon, 02 May 2005 18:59:12 +0000, pete wrote:
Eric Sosman wrote:
> It might be simpler to say that the function name "is"
>a pointer to the function, since there is no context in
>which it does anything other than "decay."

The function name remains an expression of a function type
when it is an operand of the address operator.
You can force a non macro invocation of a standard library
function by calling it like
(&putchar)('\n');

That's true although in practice it tends to be written as

(putchar)('\n');
which wouldn't make sense if putchar were a pointer.

But, yes, your form makes this point.
If a function name were a pointer expression,
then it would be a valid operand of the sizeof operator.
For those two reasons,
I would not say that a function name is a pointer.

It is a very similar argument to that for array names.
Array names have array type but in many cases an array "value"
is given as a pointer to the array's first element,
so in those cases it appears to be a pointer.
But it isn't and as with functions &array
and sizeof array show its true nature.

I would agree with Eric Sosman's statement to the extent
that the only use of a value of an expression of a function type,
is that a pointer can be derived from it.


Although it's flattering to learn that someone agrees with
me, it is also a bit embarrassing -- because I have come to
*dis*agree with myself ;-)

I said there was no context in which a function identifier
doesn't "decay" to a pointer to the function, but Keith
Thompson has convinced me I was wrong. Specifically:

- In the context `&func', the `func' part does not behave
like a pointer-to-function. If it did, the entire
expression would be pointer-to-pointer-to-function --
but, strangely enough, both `func' and `&func' (and
even `&&&&&&&func') are pointer-to-function.

- In the context `sizeof func', the `func' part does not
behave like a pointer-to-function. If it did, the
expression would evaluate to the size of a function
pointer, but in actuality the expression produces a
diagnostic.

The second point is debatable: since the context is not
valid C at all, its odd behavior doesn't matter.


The fact that the function name is not a pointer, is the
reason why the function name is not a valid operand of sizeof.
Function pointers are object types and valid operands of sizeof.
So, if the point is whether or not function names are pointers,
then the sizeof issue is relevant.
One might
equally well make arguments about the array-indexing operator
in the context `[4]"Hello"'; interesting things might be said,
but they'd have little to do with C.


The array indexing operator converts the array name to a pointer,
just as the * operator does with both array names and function names.

--
pete
Nov 14 '05 #14
pete <pf*****@mindspring.com> writes:
Michael Wojcik wrote:
sizeof &main;
That's the size of a pointer.
If it is, aside from that, are there any other cases where the & and
* operators have any effect when applied to a function name?


The * operator always converts the function type expression
to a pointer, prior to operating on it.


No, the * operator doesn't do any conversions. The conversion occurs
before the * operator is invoked. Perhaps this is just a matter of
terminology, but in my opinion saying that the operator converts its
operand is misleading. The * operator expects a pointer operand; it
gets one because the operand is already a pointer.

Given
int n;
the expression *n is illegal. If the * operator had the ability to
convert its operand to a pointer type, *n would be equivalent to n.
You could argue, I suppose, that the * operator converts its operand
only in certain circumstances, but I don't see any support for this
idea in the standard.
These are all valid function calls:

(putchar)('\n');
(&putchar)('\n');
(*putchar)('\n');

In the first one, the function type expression,
is converted to a pointer, by the function call operator.
The expression putchar is of function type. Since it's not the
operand of a sizeof or "&" operator, it's implicitly converted to a
pointer-to-function. The parenthesized expression is a no-op, used
only for syntactic resolution. This pointer-to-function *then*
becomes an operand of the function call operator; since the function
call operator expects a pointer-to-function, no further conversion is
necessary.
The second one has no conversions.
Agreed.
In the third one, the * operator converts the function type
expression to a pointer, then operates on it,
the result is an expression of function type
which is converted to a pointer by the function call operator.


The expression putchar is of function type. Since it's not the
operand of a sizeof or "&" operator, it's implicitly converted to a
pointer-to-function. The "*" operator expects, and gets, a pointer as
its operand; it yields an lvalue designating the thing the pointer
points to. In this case, the result is an lvalue designating the
putchar function. This is, again, an expression of function type.
Since this is also not the operand of a sizeof or "&" operator, it's
again implicitly converted to a pointer-to-function type. The
parentheses again have no semantic effect. The function call operator
expects, and gets, a pointer-to-function as its operand.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #15
Keith Thompson wrote:

pete <pf*****@mindspring.com> writes:
Michael Wojcik wrote:
sizeof &main;


That's the size of a pointer.
If it is, aside from that,
are there any other cases where the & and
* operators have any effect when applied to a function name?


The * operator always converts the function type expression
to a pointer, prior to operating on it.


No, the * operator doesn't do any conversions. The conversion occurs
before the * operator is invoked. Perhaps this is just a matter of
terminology, but in my opinion saying that the operator converts its
operand is misleading.


N869
6.3 Conversions
[#1] Several operators convert operand values from one type
to another automatically.

--
pete
Nov 14 '05 #16
pete wrote:

Keith Thompson wrote:

pete <pf*****@mindspring.com> writes:
Michael Wojcik wrote:

> sizeof &main;

That's the size of a pointer.

> If it is, aside from that,
> are there any other cases where the & and
> * operators have any effect when applied to a function name?

The * operator always converts the function type expression
to a pointer, prior to operating on it.


No, the * operator doesn't do any conversions. The conversion occurs
before the * operator is invoked. Perhaps this is just a matter of
terminology, but in my opinion saying that the operator converts its
operand is misleading.


N869
6.3 Conversions
[#1] Several operators convert operand values from one type
to another automatically.


I think you're right. It would be accurate
to say that not being the operand of & or sizeof,
is what converts the function type expression to a pointer.

--
pete
Nov 14 '05 #17
pete <pf*****@mindspring.com> writes:
Keith Thompson wrote:

[snip]
No, the * operator doesn't do any conversions. The conversion occurs
before the * operator is invoked. Perhaps this is just a matter of
terminology, but in my opinion saying that the operator converts its
operand is misleading.


N869
6.3 Conversions
[#1] Several operators convert operand values from one type
to another automatically.


Hmm, that's an odd statement. I don't have access to my copy of the
standard at the moment; I'll take a look at the context later tonight.
Maybe it's refering to arithmetic promotions?

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #18
Keith Thompson <ks***@mib.org> writes:
pete <pf*****@mindspring.com> writes:
Keith Thompson wrote:

[snip]
No, the * operator doesn't do any conversions. The conversion occurs
before the * operator is invoked. Perhaps this is just a matter of
terminology, but in my opinion saying that the operator converts its
operand is misleading.


N869
6.3 Conversions
[#1] Several operators convert operand values from one type
to another automatically.


Hmm, that's an odd statement. I don't have access to my copy of the
standard at the moment; I'll take a look at the context later tonight.
Maybe it's refering to arithmetic promotions?


Yes, it's talking about the "usual arithmetic conversions".

C99 6.3p1:

Several operators convert operand values from one type to another
automatically. This subclause specifies the result required from
such an implicit conversion, as well as those that result from a
cast operation (an explicit conversion). The list in 6.3.1.8
summarizes the conversions performed by most ordinary operators;
it is supplemented as required by the discussion of each operator
in 6.5.

6.3.1.8, "Usual arithmetic conversions", covers things like the "*"
operator in 1.2 * 3 converting its right operand from int to double.
IMHO it would make more sense to say that the right operand is
converted to double because of the context in which it appears, not
that it's converted by the operator, but that's the wording chosen in
the standard.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #19
Keith Thompson wrote:

Keith Thompson <ks***@mib.org> writes:
pete <pf*****@mindspring.com> writes:
Keith Thompson wrote:

[snip]
No, the * operator doesn't do any conversions. The conversion occurs
before the * operator is invoked. Perhaps this is just a matter of
terminology, but in my opinion saying that the operator converts its
operand is misleading.

N869
6.3 Conversions
[#1] Several operators convert operand values from one type
to another automatically.


Hmm, that's an odd statement. I don't have access to my copy of the
standard at the moment; I'll take a look at the context later tonight.
Maybe it's refering to arithmetic promotions?


Yes, it's talking about the "usual arithmetic conversions".

C99 6.3p1:

Several operators convert operand values from one type to another
automatically. This subclause specifies the result required from
such an implicit conversion, as well as those that result from a
cast operation (an explicit conversion). The list in 6.3.1.8
summarizes the conversions performed by most ordinary operators;
it is supplemented as required by the discussion of each operator
in 6.5.

6.3.1.8, "Usual arithmetic conversions", covers things like the "*"
operator in 1.2 * 3 converting its right operand from int to double.
IMHO it would make more sense to say that the right operand is
converted to double because of the context in which it appears, not
that it's converted by the operator, but that's the wording chosen in
the standard.


I had mistakenly interpreted the standard to mean
that being the operand of operators other than sizeof or &,
was the condition which caused conversion. That's close,
because if a function name isn't the operand of sizeof or &,
then it's usually the operand of some other operator,
but not always.
I can only think of two cases where a function name would be converted
without being an operand:
Initialization of a function pointer
ptr = function_name;
and a no op statement
function_name;

--
pete
Nov 14 '05 #20
pete wrote:

Keith Thompson wrote:

Keith Thompson <ks***@mib.org> writes:
pete <pf*****@mindspring.com> writes:
> Keith Thompson wrote:
[snip]
>> No, the * operator doesn't do any conversions. The conversion occurs
>> before the * operator is invoked. Perhaps this is just a matter of
>> terminology, but in my opinion saying that the operator converts its
>> operand is misleading.
>
> N869
> 6.3 Conversions
> [#1] Several operators convert operand values from one type
> to another automatically.

Hmm, that's an odd statement. I don't have access to my copy of the
standard at the moment; I'll take a look at the context later tonight.
Maybe it's refering to arithmetic promotions?
Yes, it's talking about the "usual arithmetic conversions".

C99 6.3p1:

Several operators convert operand values from one type to another
automatically. This subclause specifies the result required from
such an implicit conversion, as well as those that result from a
cast operation (an explicit conversion). The list in 6.3.1.8
summarizes the conversions performed by most ordinary operators;
it is supplemented as required by the discussion of each operator
in 6.5.

6.3.1.8, "Usual arithmetic conversions", covers things like the "*"
operator in 1.2 * 3 converting its right operand from int to double.
IMHO it would make more sense to say that the right operand is
converted to double because of the context in which it appears, not
that it's converted by the operator, but that's the wording chosen in
the standard.


I had mistakenly interpreted the standard to mean
that being the operand of operators other than sizeof or &,
was the condition which caused conversion. That's close,
because if a function name isn't the operand of sizeof or &,
then it's usually the operand of some other operator,
but not always.
I can only think of two cases where a function name would be converted
without being an operand:
Initialization of a function pointer
ptr = function_name;


I meant:

void (*ptr)(void) = function_name;

I'm under the impression that initialization in a declaration
is different from assignment.
and a no op statement
function_name;

--
pete


--
pete
Nov 14 '05 #21

In article <42***********@mindspring.com>, pete <pf*****@mindspring.com> writes:
Michael Wojcik wrote:
sizeof &main;


That's the size of a pointer.


Yes, specifically the size of a function pointer. I know that.
If it is, aside from that, are there any other cases where the & and
* operators have any effect when applied to a function name?


The * operator always converts the function type expression
to a pointer, prior to operating on it. ...


Yes, I know all of that as well. None of it answers my question,
I'm afraid.

--
Michael Wojcik mi************@microfocus.com

If Mokona means for us to eat this, I, a gentle person, will become
angry! -- Umi (CLAMP & unknown translator), _Magic Knight Rayearth_
Nov 14 '05 #22
On Tue, 03 May 2005 14:24:25 +0000, Michael Wojcik wrote:

....
I was mulling over the hypothesis that the & and * operators, when
applied to function names, simply did nothing, but your last example
made me think of a possible counterexample. Is the following a
strictly conforming expression?

sizeof &main;

Or, if you prefer the full-program version:

#include <stdio.h>
int main(void) {
printf("%lu\n", (unsigned long) sizeof &main);
return 0;
}

If it is, aside from that, are there any other cases where the & and
* operators have any effect when applied to a function name?


That's valid. Also consider that main is a valid operand of unary & but
&main is not. I.e. (as was noted elsewhere in the thread) &(main) is fine
but &(&main) isn't. So the inner & is making a difference here,
eliminating the property of "function designator" that main on its own has.
The effect is most obvious when using a macro

#define ADDR(x) (&(x))

p = ADDR(main); can be valid whereas p = ADDR(&main); cannot.

Lawrence

Nov 14 '05 #23
Keith Thompson <ks***@mib.org> writes:
Keith Thompson <ks***@mib.org> writes:
pete <pf*****@mindspring.com> writes:
Keith Thompson wrote: [snip]
No, the * operator doesn't do any conversions. The conversion occurs
before the * operator is invoked. Perhaps this is just a matter of
terminology, but in my opinion saying that the operator converts its
operand is misleading.

N869
6.3 Conversions
[#1] Several operators convert operand values from one type
to another automatically.


Hmm, that's an odd statement. I don't have access to my copy of the
standard at the moment; I'll take a look at the context later tonight.
Maybe it's refering to arithmetic promotions?


Yes, it's talking about the "usual arithmetic conversions".


Not just the usual arithmetic conversions; presumably a comment in
section 6.3 would also include the conversions mentioned in 6.3.2
(arrays to the address of their first element, function designators to
pointer-to-function, and lvalues to the value stored in the object the
lvalue references). It's true that these conversions happen for
essentially all operators other than 'sizeof' or the '&' address
operator; but whether it happens or not does depend on which operator
is applied, which I would say is the essential factor here. The
conversions in 6.3.2 also are implicit conversions (with appropriate
consideration for the "conversion" of changing an lvalue into the
value stored in the lvalue's object, which isn't exactly a conversion
in the same way that other conversions are).

C99 6.3p1:

Several operators convert operand values from one type to another
automatically. This subclause specifies the result required from
such an implicit conversion, as well as those that result from a
cast operation (an explicit conversion). The list in 6.3.1.8
summarizes the conversions performed by most ordinary operators;
it is supplemented as required by the discussion of each operator
in 6.5.

6.3.1.8, "Usual arithmetic conversions", covers things like the "*"
operator in 1.2 * 3 converting its right operand from int to double.
IMHO it would make more sense to say that the right operand is
converted to double because of the context in which it appears, not
that it's converted by the operator, but that's the wording chosen in
the standard.


It's funny. I'm used to thinking of operators as causing (doing?) the
conversions. But certainly Keith's view here is reasonable - the
contexts of initializing expressions and function arguments also
result in conversions even though no operators are there to cause
them. And the context of an initializing expression is different in a
significant way. In most contexts a string literal, being an array,
is implicitly converted into a pointer. But compare the two
initializing expressions:

char *p = "xyzzy";
char q[] = "xyzzy";

In one case the string literal is implicitly converted to a pointer;
in the other case it isn't. That looks a lot more like the conversion
is being driven by context than by which operator is used. (This
behavior of string literals is one of the cases mentioned in 6.3.2.)
Nov 14 '05 #24
Tim Rentsch <tx*@alumnus.caltech.edu> writes:
Keith Thompson <ks***@mib.org> writes:
Keith Thompson <ks***@mib.org> writes:
> pete <pf*****@mindspring.com> writes:
>> Keith Thompson wrote:
> [snip]
>>> No, the * operator doesn't do any conversions. The conversion occurs
>>> before the * operator is invoked. Perhaps this is just a matter of
>>> terminology, but in my opinion saying that the operator converts its
>>> operand is misleading.
>>
>> N869
>> 6.3 Conversions
>> [#1] Several operators convert operand values from one type
>> to another automatically.
>
> Hmm, that's an odd statement. I don't have access to my copy of the
> standard at the moment; I'll take a look at the context later tonight.
> Maybe it's refering to arithmetic promotions?


Yes, it's talking about the "usual arithmetic conversions".


Not just the usual arithmetic conversions; presumably a comment in
section 6.3 would also include the conversions mentioned in 6.3.2
(arrays to the address of their first element, function designators to
pointer-to-function, and lvalues to the value stored in the object the
lvalue references). It's true that these conversions happen for
essentially all operators other than 'sizeof' or the '&' address
operator; but whether it happens or not does depend on which operator
is applied, which I would say is the essential factor here. The
conversions in 6.3.2 also are implicit conversions (with appropriate
consideration for the "conversion" of changing an lvalue into the
value stored in the lvalue's object, which isn't exactly a conversion
in the same way that other conversions are).


I don't think so. As pete and I discussed upthread (and as you
mention later), the implicit conversion of an array expression to a
pointer to its first element isn't performed by an operator; it just
happens, even if there is no operator:

int arr[10];
arr;

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #25
Keith Thompson <ks***@mib.org> writes:
Tim Rentsch <tx*@alumnus.caltech.edu> writes:
Keith Thompson <ks***@mib.org> writes:
Keith Thompson <ks***@mib.org> writes:
> pete <pf*****@mindspring.com> writes:
>> Keith Thompson wrote:
> [snip]
>>> No, the * operator doesn't do any conversions. The conversion occurs
>>> before the * operator is invoked. Perhaps this is just a matter of
>>> terminology, but in my opinion saying that the operator converts its
>>> operand is misleading.
>>
>> N869
>> 6.3 Conversions
>> [#1] Several operators convert operand values from one type
>> to another automatically.
>
> Hmm, that's an odd statement. I don't have access to my copy of the
> standard at the moment; I'll take a look at the context later tonight.
> Maybe it's refering to arithmetic promotions?

Yes, it's talking about the "usual arithmetic conversions".


Not just the usual arithmetic conversions; presumably a comment in
section 6.3 would also include the conversions mentioned in 6.3.2
(arrays to the address of their first element, function designators to
pointer-to-function, and lvalues to the value stored in the object the
lvalue references). It's true that these conversions happen for
essentially all operators other than 'sizeof' or the '&' address
operator; but whether it happens or not does depend on which operator
is applied, which I would say is the essential factor here. The
conversions in 6.3.2 also are implicit conversions (with appropriate
consideration for the "conversion" of changing an lvalue into the
value stored in the lvalue's object, which isn't exactly a conversion
in the same way that other conversions are).


I don't think so. As pete and I discussed upthread (and as you
mention later), the implicit conversion of an array expression to a
pointer to its first element isn't performed by an operator; it just
happens, even if there is no operator:

int arr[10];
arr;


Well it's some pretty inconsequential semantic hairs we're splitting
here. There's support for the view that operators are what's causing
the conversion in both cases. Section 6.3.1 is titled "Arithmetic
Operands"; section 6.3.2 is titled "Other Operands". Also, reading
6.8.3 on Expression statements allows a reasonable conclusion that
there is an implicit '(void)' operator being applied in such cases.

But none of this matters; whether conversions are "caused" by
operators or not doesn't change that conversions are automatically
performed in the context of some operators and not others. Section
6.3 (both 6.3.1 and 6.3.2) lists the cases where a class of
conversions happens for several or most operators; other cases where
conversions apply only in the context of a particular operator
(whether the operator "causes" them or not) are mentioned in 6.5. The
cases in 6.5 are different because they apply only in the case of
particular operators rather than being more general. The specific
cases include:

assignment
== and !=
?:
&& and || arguably perform conversion of the implicit '0' being
tested to a null pointer value of the appropriate type

The point of 6.3 is to give the implicit conversions that are
performed by classes of operators (or if you prefer, apply in the
context of classes of expressions), whereas the implicit conversions
mentioned in 6.5 are performed just by particular operators (or if you
prefer, apply only in the context of particular kinds of expressions).
That's the point I was trying to make in talking about 6.3 p1.
Nov 14 '05 #26
On Wed, 04 May 2005 12:05:06 GMT, pete <pf*****@mindspring.com> wrote:
pete wrote:

<snip>
I can only think of two cases where a function name would be converted
without being an operand:
Initialization of a function pointer
ptr = function_name;


I meant:

void (*ptr)(void) = function_name;

I'm under the impression that initialization in a declaration
is different from assignment.

Initialization of an automatic scalar struct or union by a single
expression is effectively the same as assignment, and of a static
(duration) one is pretty similar except that must be a constant
expression (computable at compile time) and the 'assignment' is
effectively done before program execution begins.

Declarations differ in that a struct may be initialized, and an array
must be if at all, by a braced list, or a char or wchar array by a
string literal effectively treated as a list of its characters (modulo
the trailing null not fitting); assignment cannot do this. And in C99,
the components of a braced initializer may be 'designated' into
specific array elements or struct members.
and a no op statement
function_name;

Of course both of these (decl = init; and name;) are expressions, just
not operands as strictly defined, and the decay in 6.3.2.1p4 (also
array in p3 and other deref in p2) are stated for 'expression'
although listed under 'Other Operands'. And although 6.5p1 defines
expressions as made up of operators and operands and 6.4.6p2 operand
as being acted on by an operator, it is clear from syntax and
semantics that a (lone) primary-expression with no operators is a
valid expression; this is reasked and (usually) rediscussed every
month or so on comp.std.c.

- David.Thompson1 at worldnet.att.net
Nov 14 '05 #27
Dave Thompson wrote:

On Wed, 04 May 2005 12:05:06 GMT, pete <pf*****@mindspring.com> wrote:
pete wrote:

<snip>
I can only think of two cases
where a function name would be converted
without being an operand:
Initialization of a function pointer
ptr = function_name;


I meant:

void (*ptr)(void) = function_name;

I'm under the impression that initialization in a declaration
is different from assignment.

Initialization of an automatic scalar struct or union by a single
expression is effectively the same as assignment, and of a static
(duration) one is pretty similar except that must be a constant
expression (computable at compile time) and the 'assignment' is
effectively done before program execution begins.

Declarations differ in that a struct may be initialized, and an array
must be if at all, by a braced list, or a char or wchar array by a
string literal effectively treated as a list of its characters (modulo
the trailing null not fitting); assignment cannot do this. And in C99,
the components of a braced initializer may be 'designated' into
specific array elements or struct members.
and a no op statement
function_name;

Of course both of these (decl = init; and name;) are expressions, just
not operands as strictly defined, and the decay in 6.3.2.1p4 (also
array in p3 and other deref in p2) are stated for 'expression'
although listed under 'Other Operands'. And although 6.5p1 defines
expressions as made up of operators and operands and 6.4.6p2 operand
as being acted on by an operator, it is clear from syntax and
semantics that a (lone) primary-expression with no operators is a
valid expression; this is reasked and (usually) rediscussed every
month or so on comp.std.c.


Thank you.

--
pete
Nov 14 '05 #28

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

1 post views Thread by John Miles | last post: by
11 posts views Thread by JKop | last post: by
26 posts views Thread by Adam Warner | last post: by
13 posts views Thread by munni | last post: by
12 posts views Thread by srinivas.satish | last post: by
12 posts views Thread by claudiu | last post: by
12 posts views Thread by Googy | last post: by
2 posts views Thread by Rahul | last post: by
20 posts views Thread by MikeC | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.