224

In one of my project source files, I found this C function definition:

int (foo) (int *bar)
{
    return foo (bar);
}

Note: there is no asterisk next to foo, so it's not a function pointer. Or is it? What is going on here with the recursive call?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user1859094
  • 1,899
  • 2
  • 12
  • 5
  • 8
    No, it is not a function pointer - it is still a regular function named foo. – Nemanja Boric Nov 28 '12 at 08:29
  • 1
    Is this the complete function ? – asheeshr Nov 28 '12 at 08:30
  • 3
    do you have evidence that this function is used in a useful context? – moooeeeep Nov 28 '12 at 08:32
  • 1
    ...looks like some dummy function that was perhaps just written to see if it compiles, in existing source, and should have been removed. I'd remove it (if that is what the function really does), since at best it will be infinite loop (I'm not sure if C compiler is allowed to optimize that tail call to jump), at worst stack overflow. – hyde Nov 28 '12 at 08:33
  • 3
    Parentheses in C declarations help to amke the language ambiguous. Quick, what is `a(b);`? Declaration of `b` as a variable of type `a`? Or a call to function `a` with argument `b`? The difference is syntactic, and you cannot know which way to even parse it without looking up the declaration info of `a`; i.e. are those postfix function call parentheses, or optional parentheses around a declarator. – Kaz Nov 28 '12 at 20:02
  • I was going to ask this very question. Why in the world is this deemed to be legal? That [this syntax is legal (ideone link)](http://ideone.com/kF8zYx) makes an absolute mess of my parser! My parser's only response is "Don't do that then". – David Hammen Jul 29 '14 at 03:52

3 Answers3

344

In the absence of any preprocessor stuff going on, foo's signature is equivalent to

int foo (int *bar)

The only context in which I've seen people putting seemingly unnecessary parentheses around function names is when there are both a function and a function-like macro with the same name, and the programmer wants to prevent macro expansion.

This practice may seem a little odd at first, but the C library sets a precedent by providing some macros and functions with identical names.

One such function/macro pair is isdigit(). The library might define it as follows:

/* the macro */
#define isdigit(c) ...

/* the function */
int (isdigit)(int c) /* avoid the macro through the use of parentheses */
{
  return isdigit(c); /* use the macro */
}

Your function looks almost identical to the above, so I suspect this is what's going on in your code too.

Community
  • 1
  • 1
NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • 2
    That may be the case here as well; I didn't look for macros... And I did not knew that macro expansion does not take place within parentheses, Thanks for pointing that out! – user1859094 Nov 28 '12 at 08:49
  • 13
    @user1859094: On second look, this is almost certainly what's going on in your code. The `foo(bar)` inside the function is using the corresponding macro. – NPE Nov 28 '12 at 09:09
  • 79
    @user1859094 macro expansion does take place within parentheses, but expansion of a function-like macro only takes place if the next token is a left parenthesis (C99, 6.10.3§10), thus `foo (int* bar)` would get replaced, but not `(foo) (int *bar)` (the next token after `foo` is `)`) – Virgile Nov 28 '12 at 09:48
  • 4
    How would such a function be called? Would you call it with the parentheses as well? For example, would this work: `(isdigit)(5)`? – gcochard Dec 05 '12 at 19:14
  • 4
    @Greg: Right, that's exactly how you'd call it. – NPE Dec 05 '12 at 19:27
  • 1
    @Greg: mainly you'd take the address of it and stick it in a function pointer to call later. That's the main point of this technique -- you can define something as a macro in your library header and users can still take the address as if it was a function. – Chris Dodd Dec 13 '12 at 04:28
  • Gosh... macro's 20 years ago I have searched hours to find that missing parentheses on macro's cause division to return unexpected values. – bart s Dec 14 '12 at 13:40
  • It's worth noting that the definition in the question will work *only* if `foo` is defined as a macro. If it isn't, the `return` statement is infinitely recursive. It would probably benefit from `#ifdef foo`, though I'm not sure what it should do if `foo` *isn't* defined as a macro (perhaps a `#error`). – Keith Thompson Jan 03 '18 at 17:43
  • To make this answer a bit more complete, I think it would be beneficial to show how the macro and function is called. This feature basically is useful when both a macro and function with the same name exists. Thus when calling the function, you surround it parentheses so that you don't get unintended macro expansion, i.e. (idigit)(4) will call the function, not the macro. – jersey bean Aug 25 '20 at 21:43
38

The parantheses don't change the declaration - it's still just defining an ordinary function called foo.

The reason that they have been used is almost certainly because there is a function-like macro called foo defined:

#define foo(x) ...

Using (foo) in the function declaration prevents this macro from being expanded here. So what is likely happening is that a function foo() is being defined with its body being expanded from the function-like macro foo.

caf
  • 233,326
  • 40
  • 323
  • 462
  • 5
    Nice deduction (though using parentheses for this purpose should be punishable by law). – ugoren Nov 28 '12 at 08:47
  • 3
    @ugoren: using parens around the function name is about the only way to prevent a macro expansion for a function-like macro. At times it's a necessary tool. – Michael Burr Nov 28 '12 at 09:19
  • 7
    @MichaelBurr, there's also the option of not having a macro and function with the same name. I know you can't always control everything, but if you reached this solution, I'd say something is very wrong. – ugoren Nov 28 '12 at 09:23
-2

The parentheses are meaningless.
The code you show is nothing but an infinite recursion.

When defining a function pointer, you sometimes see strange parentheses that do mean something. But this isn't the case here.

ugoren
  • 16,023
  • 3
  • 35
  • 65
  • 9
    Evidently not; the parentheses prevent macro expansion. See the accepted answer. – Kevin Nov 28 '12 at 22:53
  • 13
    @Kevin, My answer is about the code shown, and is correct for it. In almost any C question here, assuming unknown preprocessor definitions can change everything. In this case, answers that consider the preprocessor are indeed better, but it doesn't make mine incorrect. – ugoren Nov 29 '12 at 09:07