当解除引用和后递增指向函数指针的指针时,首先会发生什么?

时间:2011-02-24 18:07:37

标签: c function-pointers post-increment

鉴于此代码:

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

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

 Thunk Codex[] = { foo, bar };

 gFP = Codex;

 (*gFP++)();

函数调用是在增量之前还是之后发生的?
即:这会打印“Foo Foo Foo ......”还是“Foo Bar”?

3 个答案:

答案 0 :(得分:4)

这只是我个人的看法。我不是100%确信这是正确的。 所以,如果我的回答是错误的,请原谅我。

C99 6.5.2.2/10 函数调用表示:

  

评估的顺序   功能指示符,实际   参数和子表达式   实际参数未指定,   但之前有一个序列点   实际的电话。

C99 6.5.2.4/2 后缀增量和减量运算符表示:

  

更新存储的副作用   应该发生操作数的值   在前一个和下一个之间   序列点。

后增量算子的副作用在之前的某个地方完成 下一个序列点。 假设表达式f( x ), 我认为在评估fx后会有一个序列点,并且 在函数调用之前。 因此,gFP++的副作用将在函数调用之前完成, 并且问题中的代码应打印Foo Bar

修改 我在C99和C ++中删除了附件C中的引号,并添加了引号 C99。
可能以前的报价对这个问题不明确。

答案 1 :(得分:1)

取消引用首先发生。这与任何其他后增量相同:使用原始值。

例如,请参阅Post Increment with respect to Sequence Points

但是,您的问题似乎是foo()内部使用的函数指针是否会调用foo()bar()

http://newsgroups.derkeiler.com/Archive/Comp/comp.std.c/2009-10/msg00053.html是comp.std.c中的讨论,其标题为“序列点问题”,正是在这一点上进行了论述。我不认为它达成了共识,但双方都有很好的论据。

通过我之前阅读的标准,这将调用未定义的行为。

对函数的调用充当序列点,但是附录C仅表示它作为相对于作为参数传入的表达式的序列点 - 它们保证被评估,但没有其他必然(在{{ 1}}访问f(i++) + g(j++)中的ig()中的j会调用未定义的行为。)

然而,6.5.5.2(第10页)说:

  

之后有一个序列点   评估功能指示符   和之前的实际论点   实际的电话。

表示 f()进行排序。

答案 2 :(得分:0)

operator precedence table显示C的操作顺序。

在您的示例中,gFP++具有最高优先级,后跟*gFP

但是,在完成所有其他操作之前,不会进行增量。

所以你最终得到的是取消引用gFP,然后是函数调用,然后gFP的值递增。

所以你最终会出现堆栈溢出。