我不明白后缀和前缀递增或递减的概念。谁能给出更好的解释?
13 回答
到目前为止,所有四个答案都是不正确的,因为它们断言了特定的事件顺序。
相信“都市传说”导致许多新手(和专业人士)误入歧途,即关于表达式中的未定义行为的问题层出不穷。
所以。
对于内置的 C++ 前缀运算符,
++x
递增x
并产生(作为表达式的结果)x
作为左值,而
x++
递增x
并产生(作为表达式的结果) 的原始值x
。
特别是,对于的原始值的增加和产生,没有隐含的x++
时间顺序x
。编译器可以自由地发出产生 的原始值的机器代码x
,例如它可能存在于某个寄存器中,并且延迟增量直到表达式结束(下一个序列点)。
错误地认为增量必须先出现的人,而且他们很多,通常会得出结论,某些表达式必须具有明确定义的效果,而实际上它们具有未定义的行为。
int i, x;
i = 2;
x = ++i;
// now i = 3, x = 3
i = 2;
x = i++;
// now i = 3, x = 2
'Post' 表示之后 - 即在读取变量后完成增量。'Pre' 表示之前 - 因此变量值首先递增,然后在表达式中使用。
后缀增量x++
和前缀增量之间的区别++x
恰恰在于这两个运算符如何评估它们的操作数。后缀增量在概念上复制内存中的操作数,递增原始操作数并最终产生副本的值。我认为最好通过在代码中实现运算符来说明这一点:
int operator ++ (int& n) // postfix increment
{
int tmp = n;
n = n + 1;
return tmp;
}
上面的代码将无法编译,因为您无法为原始类型重新定义运算符。编译器也无法判断我们在这里定义的是后缀运算符而不是前缀,但让我们假设这是正确且有效的 C++。可以看到后缀运算符确实作用于它的操作数,但是它返回的是自增之前的旧值,所以表达式的结果x++
是自增之前的值。x
但是,增加。
前缀增量也会增加其操作数,但它会在增量之后产生操作数的值:
int& operator ++ (int& n)
{
n = n + 1;
return n;
}
这意味着表达式++x
计算为增量x
后的值。
因此很容易认为该表达式++x
等价于 assignmnet (x=x+1)
。然而,情况并非如此,因为增量是一种在不同上下文中可能意味着不同事物的操作。在简单的原始整数的情况下,确实++x
可以替代(x=x+1)
. 但是在类类型的情况下,例如链表的迭代器,迭代器的前缀增量绝对不意味着“向对象加一”。
没有人回答这个问题: 为什么这个概念令人困惑?
作为一名计算机科学专业的本科生,由于我阅读代码的方式,我花了一段时间才理解这一点。
以下不正确!
x = y++
X 等于 y后增量。这在逻辑上似乎意味着在增量操作完成后X 等于 Y 的值。后的意思。
或者
x = ++y
X 等于 y预增量。这在逻辑上似乎意味着在增量操作完成之前X 等于 Y 的值。Pre的意思是之前。
它的工作方式实际上是相反的。这个概念令人困惑,因为该语言具有误导性。在这种情况下,我们不能使用这些词来定义行为。
x=++y 实际上读作 X 等于递增后的 Y 的值。
x=y++ 实际上被读取为 X 等于增量之前的 Y 的值。
单词 pre 和 post相对于英语的语义是倒退的。它们仅表示 ++ 与 Y 的关系。仅此而已。
就个人而言,如果我可以选择,我会转换 ++y 和 y++ 的含义。这只是我必须学习的习语的一个例子。
如果有这种疯狂的方法,我想简单地知道。
谢谢阅读。
这很简单。两者都会增加变量的值。以下两行是相等的:
x++;
++x;
不同之处在于,如果您使用正在递增的变量的值:
x = y++;
x = ++y;
在这里,两条线都将 y 的值加一。但是,第一个将增量前的 y 值赋给 x,第二个将增量后的 y 值赋给 x。
所以只有当增量也被用作表达式时才有区别。返回值后增量递增。预增量在之前递增。
int i = 1;
int j = 1;
int k = i++; // post increment
int l = ++j; // pre increment
std::cout << k; // prints 1
std::cout << l; // prints 2
后增量意味着该值i
在分配给 后会增加k
。但是,预递增意味着值 j 在分配给 之前递增l
。
这同样适用于减量。
后增量:
int x, y, z;
x = 1;
y = x++; //this means: y is assigned the x value first, then increase the value of x by 1. Thus y is 1;
z = x; //the value of x in this line and the rest is 2 because it was increased by 1 in the above line. Thus z is 2.
预增量:
int x, y, z;
x = 1;
y = ++x; //this means: increase the value of x by 1 first, then assign the value of x to y. The value of x in this line and the rest is 2. Thus y is 2.
z = x; //the value of x in this line is 2 as stated above. Thus z is 2.
由于我们现在有内联的 javascript 片段,我不妨添加一个 pre 和 pos 增量的交互式示例。它不是 C++,但概念保持不变。
let A = 1;
let B = 1;
console.log('A++ === 2', A++ === 2);
console.log('++B === 2', ++B === 2);
后增量(a++)
如果 int b = a++,那么这意味着
int b = a;
a = a+1;
这里我们将值加 1。在进行增量之前返回值,
例如 a = 1; b = a++;
那么 b=1 和 a=2
预增量(++a)
如果 int b = ++a; 那么这意味着
a=a+1;
int b=a ;
预增量:这会将主值加 1。递增后返回值,对于 a = 1; b = ++a; 那么 b=2 和 a=2。
#include<stdio.h>
void main(){
char arr[] ="abcd";
char *p=arr,*q=arr;
char k,temp;
temp = *p++; /* here first it assigns value present in address which
is hold by p and then p points to next address.*/
k = ++*q;/*here increments the value present in address which is
hold by q and assigns to k and also stores the incremented value in the same
address location. that why *q will get 'h'.*/
printf("k is %c\n",k); //output: k is h
printf("temp is %c\n",temp);//output: temp is g
printf("*p is %c\n",*p);//output: *p is e
printf("*q is %c",*q);//output: *q is h
}
使用指针进行后增量和预增量
来自 C99 标准(C++ 应该是相同的,除非出现奇怪的重载)
6.5.2.4 后缀递增和递减运算符
约束
1 后缀递增或递减运算符的操作数应具有合格或不合格的实数或指针类型,并且应是可修改的左值。
语义
2 后缀 ++ 运算符的结果是操作数的值。得到结果后,操作数的值递增。(也就是说,将相应类型的值 1 添加到其中。)有关约束、类型和转换以及操作对指针的影响的信息,请参阅加法运算符和复合赋值的讨论。更新操作数存储值的副作用应发生在前一个序列点和下一个序列点之间。
3 后缀--操作符与后缀++操作符类似,只是操作数的值是递减的(也就是减去相应类型的值1)。
6.5.3.1 前缀递增和递减运算符
约束
1 前缀递增或递减运算符的操作数应具有合格或不合格的实数或指针类型,并且应是可修改的左值。
语义
2 前缀 ++ 运算符的操作数的值递增。结果是递增后操作数的新值。表达式 ++E 等价于 (E+=1)。有关约束、类型、副作用和转换以及操作对指针的影响的信息,请参阅加法运算符和复合赋值的讨论。
3 前缀 -- 运算符类似于前缀 ++ 运算符,只是操作数的值递减。
预增量在增量值之前,++
例如:
(++v) or 1 + v
后增量是在增加值之后,++
例如:
(rmv++) or rmv + 1
程序:
int rmv = 10, vivek = 10;
cout << "rmv++ = " << rmv++ << endl; // the value is 10
cout << "++vivek = " << ++vivek; // the value is 11
您还应该知道后自增/自减运算符的行为在 C/C++ 和 Java 中是不同的。
给定
int a=1;
在 C/C++ 中,表达式
a++ + a++ + a++
计算结果为 3,而在 Java 中计算结果为 6。猜猜为什么......
这个例子更令人困惑:
cout << a++ + a++ + a++ << "<->" << a++ + a++ ;
打印 9<->2 !! 这是因为上面的表达式等价于:
operator<<(
operator<<(
operator<<( cout, a++ + a++ ),
"<->"
),
a++ + a++ + a++
)