From the C17 standard draft (6.3.2.1 ¶4; footnote removed):
A function designator is an expression that has function type. Except when it is the operand of the
sizeofoperator, 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".
- According to the footnote which I omitted from the quote above,
sizeof f(for a function designatorf) is non-standards-conformant. - Note that the C11 standard additionally mentions the
_Alignofoperator. - Note that the C2x draft additionally mentions the
typeofoperator.
As a result (here: f is a function designator; fp is a function pointer):
- One can indicate the address of a function as
&f(explicit) orf(short). - One can make a function call as:
(&f)(args)orf(args)fp(args)or(*fp)(args)
Here,
- left-hand
(&f)(args)/fp(args)is consistent with function calls technically operating on function pointers, and - right-hand
f(args)/(*fp)(args)is consistent with the naive assumption that function calls operate on functions (instead of pointers to functions).
Stylistically,
- this answer labels
&fas "always redundant", (&f)(args)is virtually unused in practice, andf/f(args)/fp(args)is the shortest style.
(For completeness' sake (and in case anyone else wants a nice summary), here is a longer list of expressions that are equivalent to f: (&f), (*******f), (***&***f), (***&**&f), (&**&***f), (&**&**&f).)
But:
When is it ever necessary or meaningful to
- write
&f(wherefis a function designator) or - write
*fp(wherefpis a function pointer)?
(By "meaningful", I mean that the behavior of the program is altered.)
- The only case I am aware of is
sizeof &f. (sizeof fis illegal, even though the GCC dialect of C permits it (at least as of version 12.2.0), but with different semantics: It seemingly returns1in all(?) cases. Why?)- I don't understand this. Letting
fauto-convert to&fwould let us simplify the standard's phrasing and givesizeof fuseful semantics too. (Perhaps this restriction exists to maintain parallelism withtypeof, which has been floating around as a compiler extension for a while.)
- I don't understand this. Letting
- I am not sure what happened with
_Alignof. - If
typeofis officially added to C with the next standard, a distinction betweentypeof &f/typeof fpandtypeof f/typeof *fpwould be obviously meaningful.