0

Possible Duplicate:
Why do all these crazy function pointer definitions all work? What is really going on?

I would be grateful for an explanation why in the code

void f(int& i)
{
  i++;
}

void g(void (passed_f)(int&),int& a)   //`passed_f` equivalent to `*passed_f`
{
  passed_f(a);
}

int main()
{
  int n=0;
  g(f,n);                              //`f` is equivalent to `&f`
}

both of the equivalences hold, in the sense of not producing any errors, and giving exactly the same result, 1. It seems, that it does not matter if we accept in g a pointer to a function, or a function itself... I also presume that [c]-tag is appropriate.

Community
  • 1
  • 1
P Marecki
  • 1,108
  • 15
  • 19
  • 2
    References don't exist in C, afaik – BlackBear Apr 19 '12 at 19:33
  • This is syntactic quirk in C regarding function pointers. Both `f` and `&f` are the same. – chrisaycock Apr 19 '12 at 19:34
  • Thx for answers; is formalized somewhere in the standard? – P Marecki Apr 19 '12 at 19:51
  • 2
    Short and easy to remember :): **Function's name is a pointer to the function itself.** (as the array name is a pointer to its first element) – Tomasz Gawel Apr 19 '12 at 20:01
  • @TomaszGawel: not always; `sizeof(&printf)` is valid, but `sizeof(printf)` is not because in the latter expression, `printf` is not a pointer. – Fred Foo Apr 19 '12 at 20:05
  • @TomaszGawel: That is not correct: the name of a function is not a pointer to the function, and the name of an array is not a pointer to the initial element of the array. – James McNellis Apr 19 '12 at 20:17
  • @larsmans - it does not undermine the principle that function name is a pointer to function itself. sizeof is an operator. and when used with brackets () expects to be given a type name not variable name. However it proves that `&f` is not equivalent to `f` when f is a function. – Tomasz Gawel Apr 19 '12 at 20:26
  • http://c0x.coding-guidelines.com/6.3.2.1.html, point 732, thx to larsmans – P Marecki Apr 19 '12 at 20:30
  • @James McNellis: you're wrong :) `int a[] = { 1, 2 }; *a == a[0]; int *b; b = a; *(b++) == a[1];` – Tomasz Gawel Apr 19 '12 at 20:34
  • @TomaszGawel See [Is array name a pointer in C?](http://stackoverflow.com/questions/1641957/is-array-name-a-pointer-in-c) for a discussion of the nature of arrays. For functions and function pointers, see my answer to the question to which I linked above. – James McNellis Apr 19 '12 at 20:38
  • @TomaszGawel: you're wrong; the `()` in a `sizeof` expression are optional and do not change the meaning of the construct. Btw., `&f` is also not the same as `f` when `f` is function pointer; `&f` evaluates to a pointer to function pointer. – Fred Foo Apr 19 '12 at 20:42
  • @James: I did **not** say that **array is a pointer** but the **array name** is a **pointer to its first element**. As far as i remember i have read this in polish translation of stroustroups c++ book (blame author, translator or my week or wicked memory ;) but i strongly convinced that it true ;) – Tomasz Gawel Apr 19 '12 at 20:45
  • @larsmans: having `char c = 'c';` then `sizeof(char) == sizeof c;` but either `sizeof(c)` or `sizeof char` are invalid - and this is **surely** from Kernighan, Ritchie, ANSI C programming language (polish translation, too) :) – Tomasz Gawel Apr 19 '12 at 20:50
  • @TomaszGawel: correction, the `()` is optional except when used with types (probably because `sizeof unsigned long` would cause trouble in the grammar). But `sizeof(c)` is valid by the rule that any expression can be parenthesized. – Fred Foo Apr 19 '12 at 21:03
  • @TomaszGawel: Even that statement is false. If it was true that an array name is a pointer to its initial element, then given `int v[100];`, it would also be true that `sizeof(v) == sizeof(int*)`. But that is surely not true. Similarly, it would mean that `int** p = &v;` would be valid, but it is not (because `&v` is of type `int(*)[100]`, not `int**`). – James McNellis Apr 19 '12 at 21:06
  • @James McNellis: `&varName` is not of any type it is a reference to existing address in memory. Please read, something about pointers and references - stroustroup recommended. You can set pointer to point at any address in memory - but not always it makes sense. Having `int v[10];` with `&v` you retrieve address of pointer so in fact the address of something that stores another address of something else. – Tomasz Gawel Apr 19 '12 at 22:53
  • @TomaszGawel: Every expression in C++ has a type. If `varName` has type `X` then `&varName` has type "pointer to `X`" even for array types. There are no references involved and the address of an array is not the same as the address of a pointer. – CB Bailey Apr 20 '12 at 05:49
  • @Charles Bailey: expression `&varName` does not have type pointer. it only retrieves the physical address of to where the pointer can be set - that's delicate difference. Humanly speaking you can set "the pointer to int" to point at "some int variable's address in memory" (which int turn - the address i mean - you retrieve with unary operator &) – Tomasz Gawel Apr 20 '12 at 09:34
  • @TomaszGawel: That's simply not true. `&varName` is an expression so _must_ have a type. From the standard 5.3.1: "The result of the unary `&` operator is a pointer to its operand. The operand shall be an lvalue or a _qualified-id_. If the operand is a _qualified-id_ [...snip...]. Otherwise, if the type of the expression is `T`, **the result has type "pointer to `T`"** and is a prvalue that is the address of the designated object or a pointer to the designated function." – CB Bailey Apr 20 '12 at 09:42
  • @Charles Bailey: You are right. I used to diffrentiate between the pointer variable and the address it points at, and associated the pointers value with the address, which seems (due to quoted standard) to be false. Your point :) – Tomasz Gawel Apr 20 '12 at 09:55

2 Answers2

2

passed_f is indeed equivalent to *passed_f, the compiler will create the same output from both. The difference is just idiomatic. Some people prefer the latter form, as it expresses more clearly that we have a pointer to a function, and this notation is more consistent with pointer notation used for other types.

Péter Török
  • 114,404
  • 31
  • 268
  • 329
2

Function pointers are special in C:

  • the name of a function, say f is a function designator, while &f is a function pointer;
  • indirecting a function pointer evaluates to a function designator;
  • indirecting a function designator evaluates to the function designator itself;
  • it follows that you can call a function pointer f as f(), (*f)(), (**f)(), etc.

If you think of function names as being pointers for almost all purposes, this makes some sense. Try compiling this version of Hello World:

int main()
{
    // try replacing * with & or adding more *s
    (*printf)("Hello, world!\n");
    return 0;
}

In the C standard, this is covered in paragraph 6.3.2.1. Not sure about the C++ standard.

Fred Foo
  • 355,277
  • 75
  • 744
  • 836