嵌套赋值语句和副作用

时间:2013-11-11 02:02:33

标签: c side-effects

在阅读 C编程语言时,我注意到在评估顺序部分的优先级中它指出“...函数调用,嵌套赋值语句和增量和递减运算符导致“副作用”......“。

我正在尝试查找导致未定义行为的嵌套赋值语句的一些示例。在本书中,它指出以下是 ok

int nl, nw, nc;
nl = nw = nc = 0;

nlnwnc都将被分配0

然后,我遇到this声明:

x = y = y = z/3;    

“推荐”。所以我的问题是,这个陈述会出现什么问题?作业与右侧相关联,因此该陈述将等同于:

x = (y = (y = z/3));    

对我来说,y = z/3x = z/3似乎非常清楚。所以,如果是这种情况,那么任何人都可以给我一个嵌套赋值语句的例子,它可能导致未定义的行为,如果没有,你能解释为什么前面的语句是未定义的。

3 个答案:

答案 0 :(得分:4)

赋值语句不限于单个变量。除其他外,您可以分配给数组的元素。

考虑这个嵌套赋值的例子:

int a[] = {100, 200};
a[a[1]] = a[1] = 0;

如果您评估分配顺序,它应该如下工作:

a[1] = 0

完成此作业后,a如下所示:{100, 0}

a[a[1]] = 0

知道a[1]为零,这与a[0] = 0相同,因此数组应如下所示:{0, 0}

然而,问题在于您现在依赖于a[1] = 0的副作用在您进入下一个作业时完成的事实:否则,您将{0}分配给a[100] ,这是超过数组末尾的方式。

由于在没有sequence points的情况下没有定义副作用的完成顺序,这是未定义的行为。

答案 1 :(得分:1)

http://c-faq.com/expr/seqpoints.html有几点涉及您的问题。特别是:

y = y可能很好

x = y = y = z/3;

这样的表达式
y = y++

未定义,因为y的值在序列点之前被修改了两次。

答案 2 :(得分:1)

当某些表达式具有副作用时,嵌套赋值只会导致未定义的行为。在您发布的示例中,没有副作用,因此没有未定义的行为。但是,您链接到的页面也提供了未定义行为的示例:

x = y = y++;

他们并不是说所有嵌套的赋值都会导致未定义的行为,但只是你应该避免使用它们以避免使用那些行为。这更像是一种风格推荐。