C++ 为什么在条件评估中最终要进行后缀增量?
GDB显示在整个评估C++ 为什么在条件评估中最终要进行后缀增量?,c++,c,C++,C,GDB显示在整个评估=之后,obj->start_point增加 但是C Primer Plus告诉我++的优先级高于= 那么为什么obj->start\u point不首先递增呢?这本书错了吗 if (obj->start_point++ >= obj->data + obj->data_size) { 它确实具有更高的优先级。问题是variable++返回增量之前的值。如果要返回新值,必须在其前面加前缀:++variable 在您的情况下:如果(++obj->sta
=
之后,obj->start_point
增加
但是C Primer Plus告诉我++
的优先级高于=
那么为什么obj->start\u point
不首先递增呢?这本书错了吗
if (obj->start_point++ >= obj->data + obj->data_size) {
它确实具有更高的优先级。问题是
variable++
返回增量之前的值。如果要返回新值,必须在其前面加前缀:++variable
在您的情况下:如果(++obj->start\u point>=obj->data+obj->data\u size){
执行variable++
相当于调用此函数:
int increment_posfix(int *x)
{
int temp = *x;
*x = *x + 1;
return temp;
}
执行++变量时
相当于:
int increment_prefix(int *x)
{
*x = *x + 1;
return *x;
}
优先级仅控制运算符与操作数的分组,而不控制表达式的求值顺序
++
运算符的副作用不必在评估后立即应用,只需在下一个序列点之前应用
编辑
您当然可以查看生成的汇编代码,以了解编译器如何处理该特定情况,只需注意这取决于代码以及您如何编译它(不同的优化级别可能会影响它)
除了少数例外情况1,C不要求以任何特定顺序(从左到右、从右到左或任何其他顺序)计算表达式。在这种情况下,最重要的是我们将obj->data+obj->data\u size
的结果与obj->start\u point++
的结果进行比较。以下任何一种评估顺序都是可能的:
Order 1
–––––––
tmp1 = obj->data + obj->data_size
result = obj->start_point >= tmp1
obj->start_point = obj->start_point + 1
Order 2
–––––––
tmp1 = obj->start_point
obj->start_point = obj->start_point + 1
tmp2 = obj->data + obj->data_size
result = tmp1 >= tmp2
Order 3
–––––—–
tmp1 = obj->start_point
tmp2 = obj->data + obj->data_size
obj->start_point = obj->start_point + 1
result = tmp1 >= tmp2
或者完全是别的什么
obj->start_point++
和obj->data+obj->data_size
的求值甚至可以相互交错-毕竟,obj->start_point
、obj->data
和obj->data_size
中的每一个都是需要求值的表达式
只要结果是正确的-我们将比较obj->start_point
上后缀++
操作符的结果与添加obj->data
和obj->data_size
的结果-编译器在如何排序每个子表达式的求值方面有很大的自由度,而这种排序不必进行修改在整个程序中保持一致(同一程序中其他地方的类似表达式的计算方式可能不同)
从评论中回答leoleohu的问题
莱奥廖胡问道
但我的问题仍然存在,谁决定postfix++在>=之后执行,prefix++在>=之前执行
这取决于编译器,对于同一代码中的每个表达式,它不必相同
前缀和后缀形式的++
和--
运算符都有结果和副作用
obj->start_point++
的结果是obj->start_point
的当前值。副作用是在表达式中的obj->start_point
中添加1
obj->start_point++ >= obj->data + obj->data_size
将obj->start_point++
(当前值obj->start_point
)的结果与obj->data+obj->data_size
的结果进行比较
在obj->start_point
中添加1的副作用可以发生在计算后的任何点上,只要它发生在下一个序列点之前。它可以在比较之前或之后应用-编译器可以根据当前优化级别、表达式中的其他操作数、周围的代码等
&&
、|
、?:
和逗号运算符(与函数调用中分隔参数的逗号不同)都强制从左向右求值。
当你问“为什么它不先增加?”,你必须非常小心你所问的。当你说obj->start\u point++
时,至少会发生三件不同的事情:
obj->start\u point
的旧值,并计算一个新值,obj->start\u point+1
obj->start\u point
=
运算符将“返回”的值与子表达式obj->data+obj->data\u size
进行比较++
的后缀形式,“返回”到外部表达式的值是旧值。这正是后缀++
操作的定义。这不是一个“操作顺序”问题,而是一个“接线员是干什么的?”他问道
然后是语句“B”,它不那么有趣,而且非常明显,你甚至可能不会把它看作一个“东西”,它是,1必须在2之前发生——我们不能存储新的值,直到我们计算它之后
但是,这也是非常重要的——这甚至值得贴上“语句C”的标签——认识到我们不能说其他任何东西。我们绝对不知道(在任何绝对意义上)当事情#1发生时。我们也不知道事情#2会发生。我们所知道的是事情#2会在事情#1之后发生,在整个表达式完成之前的某个时间(也就是正式地说,在下一个序列点之前)。(因此,我们可能有四件事可以说。)
另请参见前面的问题,是的,这是后缀的全部要点,首先检查/读取变量,然后递增它。否则,请使用++obj->s