function pointers as function parameters

  • Thread starter Marlene Stebbins
  • Start date
P

pete

pete said:
Keith said:
Keith Thompson said:
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.
 
M

Michael Wojcik

That's the size of a pointer.

Yes, specifically the size of a function pointer. I know that.
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.
 
L

Lawrence Kirby

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
 
T

Tim Rentsch

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

Keith Thompson

Tim Rentsch said:
Keith Thompson said:
Keith Thompson said:
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;
 
T

Tim Rentsch

Keith Thompson said:
Tim Rentsch said:
Keith Thompson said:
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.
 
D

Dave Thompson

pete wrote:

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

pete

Dave said:
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.

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.
 

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,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top