15

I'm a little confused about the correct syntax for assigning a function pointer to a variable. If I have a function foo

int foo();

and I am assigning a pointer to foo to variable bar

void * bar;

it does not seem to matter if I use

bar = foo; 
// or 
bar = &foo; 

It seems to me that only one of these should be correct or am I missing something?

Mike
  • 47,263
  • 29
  • 113
  • 177
Richard Johnson
  • 612
  • 1
  • 9
  • 20

2 Answers2

15

foo and &foo values are equivalent in C and have same type.

The & operator here is correct but redundant.

Note that assigning a function pointer to a void * is not valid in C.

void *fp1 = foo;   // invalid
int (*fp2)() = foo;  // valid
int (*fp3)() = &foo; // valid

(These are actually declarations but the constraints of the assignment operator apply.)

ouah
  • 142,963
  • 15
  • 272
  • 331
  • `int (*fp2) = foo; ` even compiles ..no problem :)\ – Grijesh Chauhan Mar 07 '13 at 20:32
  • @GrijeshChauhan not with `-Werror`. `int (*fp2) = foo;` is actually invalid C. – ouah Mar 07 '13 at 20:34
  • OK!..for the 5 mins I thought you made mistake.. but peoples voted your answer and I know your can't make mistake so I just posted my answer instead commenting you. :) – Grijesh Chauhan Mar 07 '13 at 20:59
  • 1
    `foo` and `&foo` are not equivalent and generally do not have the same type. While `sizeof(&foo)` is perfectly valid, `sizeof(foo)` isn't. You may think of functions and pointers to them similarly to how you treat arrays of something and pointers to that same something. In most expression contexts, arrays and functions "decay" to pointers, the two exceptions being when the unary operators `&` and `sizeof` are applied to them. – Alexey Frunze Mar 07 '13 at 21:54
  • @AlexeyFrunze I explicitly use the word *value* in my answer and `sizeof` does not evaluate its operand. – ouah Mar 07 '13 at 22:02
  • 1
    Still, the statement is likely to mislead. `&(foo)` isn't the same as `&(&foo)`, so that's another context in which the two are not equivalent. I suppose that technically `&` doesn't *fully* evaluate its operand, since it doesn't do the thing that in C++ is called lvalue-rvalue conversion, and in C is called finding the value of an expression, so I suppose that technically in C lvalues are never "evaluated" since they aren't really values. This is quite a fine hair to split in lieu of finding another way of saying what needs to be said about the expression `foo`. – Steve Jessop Mar 07 '13 at 22:23
7

Let me explain a bit more.

foo and &foo values are equivalent in C and have same type.

This is not fully correct as pointed out by the comments to the answer by @ouah. Particularly:

  1. sizeof(foo) is invalid, and sizeof(&foo) is the size of a pointer.
  2. &foo is the pointer to foo, while &(&foo) is invalid.

However, they are actually the same in all the other cases, as is mentioned by the standard of C (reference to, e.g., the draft of C11):

6.3.2.1.4: 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".

The sizeof and unary & operators are the only two exceptions when a function designator is not converted to a pointer.

P.S. You can also find why sizeof(foo) and &(&foo) is invalid:

6.5.3.2.1: The operand of the unary & operator shall be either a function designator, the result of a [] or unary * operator, or an lvalue that designates an object that is not a bit-field and is not declared with the register storage-class specifier.

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

Community
  • 1
  • 1
Colliot
  • 1,522
  • 3
  • 16
  • 29