【问题标题】:C sequence points within expression containing function calls and post-increments包含函数调用和后增量的表达式中的 C 序列点
【发布时间】:2015-01-30 04:14:05
【问题描述】:

下面的代码打印了什么?

#include <stdio.h>


int f(int x) { printf("%d", x); return 1; }

int main() {
    int i = 0;
    f(i++) && f(i++);
}

它是否保证是01,或者它可以是00,两个后增量都发生在语句之后?

【问题讨论】:

  • 保证为01

标签: c sequence-points


【解决方案1】:

根据 C99 C11,两者的附录 C,在所有参数都已在&amp;&amp; 运算符的第一个操作数的结尾。

所以你受到双重保护,或者正如我们在澳大利亚所说,如果鲨鱼没有抓住你,鳄鱼就会(a)

标准的两次迭代之间的措辞略有不同,但具有相同的效果。 C11 是(为了便于阅读,稍作解释):

C11:

以下是前面介绍的顺序点:

  • 在函数调用和实际调用中函数指示符和实际参数的评估之间。
  • 在以下运算符的第一个和第二个操作数的计算之间:'&amp;&amp;' '||' '?' ','

&amp;&amp; 的短路特性也意味着表达式的左侧将首先被计算。

所以您的 sn-p 定义明确,输出将是 01


(a) 实际上,我认为澳大利亚的任何人都不会这么说,除了史蒂夫·欧文,他既没有被鲨鱼也没有被抓到。鳄鱼,并且可能会欣赏这种讽刺。

【讨论】:

  • 我不相信函数调用是相关的。函数体在对其参数求值后进行排序,但参数本身不相对于彼此或表达式的任何其他部分进行排序。 f(i++)+f(i++) 是 UB。如果i++ 在函数内部,f(&amp;i)+f(&amp;i) 将导致 i 为 2,总和为 1,但输出可能为任一方向,因为未指定调用顺序,但调用不能交错。
  • @rici,目的是表明在这种情况下,两个 i++ 操作之间有 两个 序列点,第一个在调用第一个函数之前,第二个在&amp;&amp;。你是正确的,只有一个是需要的。
  • 6.5.2.2/10 表示参数和函数指示符在函数体之前排序,调用表达式中的所有其他子表达式相对于函数体的排序是不确定的,但什么也没说关于参数和函数指示符的评估如何相对于彼此进行排序。所以两个i++ 参数评估是无序的,因此是UB。只有i++ 在函数体中(int f(int *x){return (*x)++;},才会像我之前所说的那样不确定地对后增量进行排序。
猜你喜欢
  • 1970-01-01
  • 2012-08-11
  • 1970-01-01
  • 2019-01-23
  • 2013-01-19
  • 2017-02-11
  • 2014-07-18
  • 2022-11-18
  • 2017-08-04
相关资源
最近更新 更多