C&C++   发布时间:2022-04-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了foo(i)foo(i)是否在ANSI C中未定义?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
这是一个示例代码段:

int i = 4,b;    
b = foo(i++) + foo(i++);

我很确定它不是未定义的,因为在调用foo之前有一个序列点.但是,如果我使用-Wall标志编译代码,则会生成编译器警告,警告:“i”上的操作可能未定义.我意识到它可能,但我只想仔细检查一下我是否正确.

解决方法

行为未定义.

b = foo(i++) + foo(i++);

正如你所说,在第一个i的评估和foo的调用之间存在一个序列点,同样在第二个i和call foo的评估之间也存在一个序列点.但是,在i的两次评估之间(或者更确切地说,在它们的副作用之间)(修改i)之间没有(必然的)序列点.

引用2011 ISO C标准的N1570草案,第6.5.2.2p10节:

第二句在这里意义重大:对i的两个评价是“不确定的
对两个函数调用进行了排序,这意味着它们可以在调用foo之前或之后发生.(但它们并没有被排除;它们中的每一个都在调用之前或之后发生,但它未指定哪个.)

并且6.5p2说:

将这些放在一起,符合要求的实现可以按以下顺序评估表达式:

>评估第一个i并将值保存在某处.
>评估第二个i并将值保存在某处.
>调用foo,将第一个保存的值作为参数传递.
>调用foo,将第二个保存的值作为参数传递.
>添加两个结果.
>将总和存储在B中.

步骤1和2之间没有序列点,两者都修改i,因此行为未定义.

(这实际上是一个轻微的过度简化;修改i的副作用可以与i的结果的确定分开.

底线:我们知道

b = i++ + i++;

由于已经反复解释的原因,它具有未定义的行为.在函数调用中包装i子表达式会添加一些序列点,但这些序列点不会将i的两个求值分开,因此不会导致行为定义得很好.

甚至是底线:请不要写那样的代码.即使行为得到了很好的定义,证明它并确定行为应该是更加困难.

大佬总结

以上是大佬教程为你收集整理的foo(i)foo(i)是否在ANSI C中未定义?全部内容,希望文章能够帮你解决foo(i)foo(i)是否在ANSI C中未定义?所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。