加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

foo(i)foo(i)是否在ANSI C中未定义?

发布时间:2020-12-16 09:49:55 所属栏目:百科 来源:网络整理
导读:这是一个示例代码段: int i = 4,b; b = foo(i++) + foo(i++); 我很确定它不是未定义的,因为在调用foo之前有一个序列点.但是,如果我使用-Wall标志编译代码,则会生成编译器警告,警告:“i”上的操作可能未定义.我意识到它可能,但我只想仔细检查一下我是否正确
这是一个示例代码段:

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节:

There is a sequence point after the evaluations of the function
designator and the actual arguments but before the actual call. Every
evaluation in the calling function (including other function calls)
that is not otherwise specifically sequenced before or after the
execution of the body of the called function is indeterminately
sequenced with respect to the execution of the called function.

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

并且6.5p2说:

If a side effect on a scalar object is unsequenced relative to either
a different side effect on the same scalar object or a value
computation using the value of the same scalar object,the behavior is
undefined. If there are multiple allowable orderings of the
subexpressions of an expression,the behavior is undefined if such an
unsequenced side effect occurs in any of the orderings.

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

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

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

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

底线:我们知道

b = i++ + i++;

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

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读