当取消引用和后递增函数指针的指针时,首先会发生什么?
给定以下代码:
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”吗?
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"?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这只是我个人的看法。我并不 100% 相信这是正确的。
所以,如果我的回答有错误,请原谅我。
C99 6.5.2.2/10函数调用说:
C99 6.5.2.4/2 后缀递增和递减运算符 说:
后增量运算符的副作用是在
下一个序列点。
假设表达式
f( x )
,我认为在计算
f
和x
之后有一个序列点,并且在函数调用之前。
所以,
gFP++
的副作用会在函数调用之前完成,问题中的代码预计会打印
Foo Bar
。编辑:
我删除了 C99 和 C++ 中附录 C 中的引号,并添加了来自
C99。
之前的引述可能对这个问题含糊其辞。
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:
C99 6.5.2.4/2 Postfix increment and decrement operators says:
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
andx
, andbefore 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.
首先发生取消引用。这与任何其他后增量相同:使用原始值。
例如,请参阅关于序列点的后增量
但是,您的问题似乎是 foo() 内部使用的函数指针是否会调用 foo() 或 bar() 。
http://newsgroups.derkeiler.com/ Archive/Comp/comp.std.c/2009-10/msg00053.html 是 comp.std.c 中的一个讨论,标题为“序列点问题”,正是针对这一点进行了争论。我认为双方没有达成共识,但双方都有很好的论据。
根据我之前阅读的标准,这将调用未定义的行为。
对函数的调用充当序列点,但附录 C 仅表示它充当相对于作为参数传入的表达式的序列点 —— 它们保证被求值,但其他任何东西都不一定会被求值(在
f( i++) + g(j++)
访问g()
中的i
或f()
中的j
code> 调用未定义的行为。)但是,6.5.5.2 (p 10) 说:
这意味着它确实对
++
进行排序。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 callfoo()
orbar()
.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 eitheri
ing()
orj
inf()
invokes undefined behavior.)However, 6.5.5.2 (p 10) says:
which means that it does sequence the
++
.运算符优先级表 显示 C 的运算顺序。
在您的示例中,
gFP++
具有最高优先级,其次是*gFP
但是,直到所有其他操作完成后才会完成增量。
所以你最终会得到的是对 gFP 进行解引用操作,然后是函数调用,然后 gFP 的值递增。
所以你最终会出现堆栈溢出。
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.