3

Given this code:

 typedef void (*Thunk)();
 Thunk* gFP;

 void foo(){ printf("Foo "); *gFP(); };
 void bar(){ printf("Bar ");

 Thunk Codex[] = { foo, bar };

 gFP = Codex;

 (*gFP++)();

Does the function call happen before or after the increment?
i.e: Will this print "Foo Foo Foo ..." or "Foo Bar"?

skaffman
  • 398,947
  • 96
  • 818
  • 769
AShelly
  • 34,686
  • 15
  • 91
  • 152

3 Answers3

4

This is just my personal view. I'm not 100% convinced that this is correct. So, please forgive me if my answer is wrong.

C99 6.5.2.2/10 Function calls says:

The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call.

C99 6.5.2.4/2 Postfix increment and decrement operators says:

The side effect of updating the stored value of the operand shall occur between the previous and the next sequence point.

The side effect of post increment operator is completed somewhere before the next sequence point. Assuming the expression f( x ), I think there is a sequence point after the evaluation of f and x, and before the function call. So, the side effect of gFP++ will be completed before the function call, and the code in the question is expected to print Foo Bar.

Edit: I removed the quotes from Annex-C in C99 and C++, and added the quotes from C99.
Probably previous quotes were indistinct regarding the question.

Ise Wisteria
  • 11,259
  • 2
  • 43
  • 26
1

The dereference happens first. This is the same thing as any other post-increment: the original value is used.

See, for instance, Post Increment with respect to Sequence Points

However, your question seems to be whether the function pointer use inside of foo() will call foo() or bar().

http://newsgroups.derkeiler.com/Archive/Comp/comp.std.c/2009-10/msg00053.html is a discussion in comp.std.c with the header "sequence point problem" that argues over precisely this point. I don't think it came to a consensus, but there were good arguments on both sides.

By my previous reading of the standard, this would invokes undefined behavior.

The call to a function acts as sequence point, but appendix C only says it acts as a sequence point relative to the expressions passed in as parameters -- they are guaranteed to be evaluated, but nothing else necessarily will (in f(i++) + g(j++) accessing either i in g() or j in f() invokes undefined behavior.)

However, 6.5.5.2 (p 10) says:

There is a sequence point after the evaluations of the function designator and the actual arguments but before the actual call.

which means that it does sequence the ++.

Community
  • 1
  • 1
wnoise
  • 9,764
  • 37
  • 47
  • For the record, Visual C++ 2005 does the increment before the function call - the code prints "Foo Bar". Are there compilers which do it differently? – AShelly Feb 24 '11 at 18:51
  • gcc 4.5.2, tcc 0.9.25, and clang 1.1 all do the increment "before" the function call. These are the only ones I have readily available to test. – wnoise Feb 24 '11 at 20:27
0

The operator precedence table shows the order of operations for C.

In your example, gFP++ has the highest precedence, followed by *gFP

However, the increment is not done until all other operations have completed.

So what you will end up with is the dereference operating on gFP, then the function call, then the value of gFP being incremented.

So you will end up with a stack overflow.

Wladimir Palant
  • 56,865
  • 12
  • 98
  • 126
Alan Geleynse
  • 24,821
  • 5
  • 46
  • 55
  • 1
    No, what happens is that the expression `*gFP++` in parenthese is evaluated first, then the function call is done. Postfix increment has a higher precendence than dereference, so the increment will be evaluated first. __However__ the result of the postfix++ operator is the _value of the operand_ (section 6.5.2.4 of ISO 9899). Which means it matters not which happens first _technically_, practically you end up calling `Codex[0]`, and later inside `foo` dereference a pointer directed at `Codex[1]`. Which, unsurprisingly, outputs "Foo", "Bar". – Damon Jun 28 '11 at 13:42