【问题标题】:order of evaluation of function parameters函数参数的评估顺序
【发布时间】:2011-07-17 18:02:54
【问题描述】:

以下操作的结果将打印什么:

x=5; 
printf("%d,%d,%d\n",x,x<<2,x>>2); 

答案:5,20,1

我认为顺序是未定义的,但我在上面找到了许多网站上的面试问题。

【问题讨论】:

  • 感谢您对缩进的帮助。我的意思是像后缀或前缀这样的运算符而不是移位。
  • 为什么你认为它是未定义的?为什么你认为评估顺序很重要?无论何时评估,每个参数都将具有相同的值。

标签: c++ c function operator-precedence


【解决方案1】:

来自 C++ 标准:

参数的评估顺序未指定。参数表达式评估的所有副作用在输入函数之前生效。后缀表达式和参数表达式列表的求值顺序未指定。

但是,只有当参数是 x&gt;&gt;=2x&lt;&lt;=2 时,您的示例才会有未定义的行为,这样 x 正在被修改。

【讨论】:

  • 如果是 &gt;&gt;=&lt;&lt;=,它将是未定义的,而不是模棱两可的
  • 歧义是正交的。真正的问题是undefinedness
【解决方案2】:

位移运算符不会修改变量的值...所以顺序无关紧要。

【讨论】:

    【解决方案3】:

    未指定评估顺序,但这并不重要,因为您根本没有修改x

    所以程序是明确定义的,答案就是给定的。

    以下内容将具有未定义的语义:

    printf("%d,%d,%d\n", x, x <<= 2, x >>= 2); 
    

    【讨论】:

    • 虽然我没有看到对您的回答投反对票,但我可以假设它就在那里,我唯一能想到的是,正如我们讨论的那样,行为不是未指定的,而是未定义的,这使您的回答不完全正确......但我不会仅仅为此而投反对票
    【解决方案4】:

    我在c++ standards找到了答案。

    第 5.2.2.8 段:

    参数的评估顺序未指定。所有副作用 的参数表达式评估在函数执行之前生效 进入。后缀表达式的求值顺序和 参数表达式列表未指定。

    换句话说,它只取决于编译器。

    【讨论】:

      【解决方案5】:

      官方 C 规范中未定义评估顺序。

      但是,出于实用性考虑,参数通常从右到左进行评估。

      在您的问题中,位移运算符不会更改 X 的值,因此评估顺序并不重要。你会得到 5,20,1,无论是从左到右、从右到左还是中间优先。

      在 C 语言中,参数按从右到左的顺序推送到堆栈中,因此第一个参数(在本例中为 char* "%d,%d,% d") 在栈顶。参数通常(但不总是)按照它们被推送的相同顺序进行评估。

      一个更能说明你在说什么的问题是:

      int i=1;
      printf("%d, %d, %d", i++, i++, i++);
      

      官方的答案是“未定义”。
      实际答案(在我尝试过的几个编译器/平台中)是“3、2、1”。

      【讨论】:

      • 那你的经验很有限。同样,一旦编译器优化掌握了如果,那么就无法确定会发生什么。
      • 所有这些假装你知道编译器在做什么的做法都是危险的。 (a) 不要这样做; (b) 看在上帝的份上,不要教它。
      • 奇怪,在我尝试过的所有实现中,您的示例给出了“3,3,3”。诚然,我只测试了三个实现(msvc10、MingW(gcc 4.5.4) 和Ideone(gcc 4.3.4)),但它们是相当广泛使用的实现。
      • @Benjamin Lindley:我还敢打赌,您可以通过使用不同的优化来改变值。
      猜你喜欢
      • 2018-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-17
      • 1970-01-01
      • 1970-01-01
      • 2020-06-07
      相关资源
      最近更新 更多