在C 11中的一个表达式中双重分配相同的变量

The C++11 standard(5.17,expr.ass)指出

In all cases,the assignment is sequenced after the value computation
of the right and left operands,and before the value computation of
the assignment expression. With respect to an
indeterminately-sequenced function call,the operation of a compound
assignment is a single evaluation

根据我的理解,所有作为给定作业的一部分的表达式将在赋值本身之前进行评估.即使我在相同的作业中修改了相同的变量,这个规则也应该是正常的,我相当肯定,这是之前的未定义的行为.

会给定代码

int a = 0;
a = (a+=1) = 10;

if ( a == 10 ) {
    printf("this is defined");
} else {
    printf("undefined"); 
}

总是评价为== 10?

解决方法

让我们重写你的代码
E1 = (E2 = E3)

其中E1是表达式a,E2是表达式a = 1,E3是表达式10.这里我们建议,赋值运算符从右到左(C11标准中的§5.17/ 1)组合.

§5.17/ 1另外说:

In all cases,the assignment is sequenced after the value computation of the right and left operands,and before the value computation of the assignment expression.

将其应用于我们的表达式意味着我们首先必须评估子表达式E1和E2 = E3.请注意,这两个评估之间没有“先后顺序”关系,但这不会导致任何问题.

id-expression E1的评估是微不足道的(结果是一个本身).赋值表达式E2 = E3的评估进行如下:

首先,两个子表达式都必须进行评估.对文字E3的评价再次微不足道(赋予价值10的价值).

(化合物)分配表达式E2的评估按以下步骤进行:

1)a = 1的行为相当于a = a 1但a只被评估一次(§5.17/ 7).在对子表达式a和1(按任意顺序)进行评估之后,对值进行左值转换,以读取存储在a中的值.

2)a(其为0)和1的值被添加(a 1),并且该添加的结果是值1的pr值.

3)在我们可以计算分配结果a = a 1之前,左操作数引用的对象的值被右操作数的值替换(§5.17/ 2).因此,E2的结果是对新值1的左值.注意,在赋值表达式的值计算之前,排除副作用(更新左操作数的值).这是上面引用的§5.17/ 1.

现在我们已经对子表达式E2和E3进行了评估,E2ref表达式的值被E3替换为10,因此E2 = E3的结果是值为10的值.

最后,值表达式E1指代被表达式E2 = E3的值所替代,我们计算为10.因此,变量赋值为包含值10.

由于所有这些步骤都有明确的定义,因此整个表达式产生了明确的值.

相关文章

/** C+⬑ * 默认成员函数 原来C++类中,有6个默认成员函数: 构造函数 析构函数 拷贝...
#pragma once // 1. 设计一个不能被拷贝的类/* 解析:拷贝只会放生在两个场景中:拷贝构造函数以及赋值运...
C类型转换 C语言:显式和隐式类型转换 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译...
//异常的概念/*抛出异常后必须要捕获,否则终止程序(到最外层后会交给main管理,main的行为就是终止) try...
#pragma once /*Smart pointer 智能指针;灵巧指针 智能指针三大件//1.RAII//2.像指针一样使用//3.拷贝问...
目录<future>future模板类成员函数:promise类promise的使用例程:packaged_task模板类例程...