后自增和前自增的概念?

发布于 2024-10-08 07:13:11 字数 36 浏览 5 评论 0原文

我不明白后缀和前缀递增或递减的概念。谁能给出更好的解释吗?

I don't understand the concept of postfix and prefix increment or decrement. Can anyone give a better explanation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

难如初 2024-10-15 07:13:11

到目前为止,所有四个答案都是不正确,因为它们断言了事件的特定顺序。

相信“都市传说”已经让许多新手(和专业人士)误入歧途,也就是说,关于表达中的未定义行为的问题层出不穷。

所以。

对于内置 C++ 前缀运算符,

++x

递增 x 并生成(作为表达式的结果)x 作为左值,而

x++

递增 x 并生成(作为表达式的结果)x 的原始值。

特别是,对于 x++ 来说,对于 x 的原始值的增量和生成并不隐含无时间排序。编译器可以自由地发出产生x原始值的机器代码,例如它可能存在于某个寄存器中,并且延迟增量直到表达式结束(下一个序列点)。

人们错误地认为增量必须首先出现,并且有很多人经常得出这样的结论:某些表达式必须具有明确定义的效果,而实际上它们具有未定义的行为。

All four answers so far are incorrect, in that they assert a specific order of events.

Believing that "urban legend" has led many a novice (and professional) astray, to wit, the endless stream of questions about Undefined Behavior in expressions.

So.

For the built-in C++ prefix operator,

++x

increments x and produces (as the expression's result) x as an lvalue, while

x++

increments x and produces (as the expression's result) the original value of x.

In particular, for x++ there is no no time ordering implied for the increment and production of original value of x. The compiler is free to emit machine code that produces the original value of x, e.g. it might be present in some register, and that delays the increment until the end of the expression (next sequence point).

Folks who incorrectly believe the increment must come first, and there are many, often conclude from that certain expressions must have well defined effect, when they actually have Undefined Behavior.

戴着白色围巾的女孩 2024-10-15 07:13:11
int i, x;

i = 2;
x = ++i;
// now i = 3, x = 3

i = 2;
x = i++; 
// now i = 3, x = 2

“Post”的意思是“之后”,即在读取变量之后完成增量。 'Pre' 表示之前 - 因此变量值首先递增,然后在表达式中使用。

int i, x;

i = 2;
x = ++i;
// now i = 3, x = 3

i = 2;
x = i++; 
// now i = 3, x = 2

'Post' means after - that is, the increment is done after the variable is read. 'Pre' means before - so the variable value is incremented first, then used in the expression.

遮云壑 2024-10-15 07:13:11

后缀增量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 在增量之后

因此很容易认为表达式 ++x 等价于 allocatemnet (x=x+1)。然而,事实并非如此,因为增量是一种在不同上下文中可能意味着不同事物的操作。在简单原始整数的情况下,++x确实可以替代(x=x+1)。但在类类型的情况下,例如链表的迭代器,迭代器的前缀增量绝对不意味着“向对象加一”。

The difference between the postfix increment, x++, and the prefix increment, ++x, is precisely in how the two operators evaluate their operands. The postfix increment conceptually copies the operand in memory, increments the original operand and finally yields the value of the copy. I think this is best illustrated by implementing the operator in code:

int operator ++ (int& n)  // postfix increment
{
    int tmp = n;
    n = n + 1;
    return tmp;
}

The above code will not compile because you can't re-define operators for primitive types. The compiler also can't tell here we're defining a postfix operator rather than prefix, but let's pretend this is correct and valid C++. You can see that the postfix operator indeed acts on its operand, but it returns the old value prior to the increment, so the result of the expression x++ is the value prior to the increment. x, however, is incremented.

The prefix increment increments its operand as well, but it yields the value of the operand after the increment:

int& operator ++ (int& n)
{
    n = n + 1;
    return n;
}

This means that the expression ++x evaluates to the value of x after the increment.

It's easy to think that the expression ++x is therefore equivalent to the assignmnet (x=x+1). This is not precisely so, however, because an increment is an operation that can mean different things in different contexts. In the case of a simple primitive integer, indeed ++x is substitutable for (x=x+1). But in the case of a class-type, such as an iterator of a linked list, a prefix increment of the iterator most definitely does not mean "adding one to the object".

も星光 2024-10-15 07:13:11

没有人回答这个问题:
为什么这个概念令人困惑?

作为一名计算机科学专业的本科生,由于我阅读代码的方式,我花了一段时间才理解这一点。

以下说法不正确!


x = y++

X 等于 y post 增量。从逻辑上讲,这似乎意味着 X 等于增量操作完成后的 Y 值。 发布意思是之后

x = ++y
X 等于 y 预增量。从逻辑上讲,这似乎意味着 X 等于增量操作完成之前的 Y 值。 Pre 意思是之前


它的工作方式实际上是相反的。这个概念令人困惑,因为语言具有误导性。在这种情况下,我们不能使用词语来定义行为。
x=++y 实际上被读取为 X 等于 Y 增量后的值。
x=y++ 实际上被读取为 X 等于 Y 增量之前的值。

pre 和 post 这两个词相对于英语语义来说是倒退的。它们仅表示 ++ 与 Y 相关的位置。仅此而已。

就我个人而言,如果可以选择,我会交换 ++y 和 y++ 的含义。这只是我必须学习的一个习语的例子。

如果有一种方法可以解决这种疯狂问题,我想简单地了解一下。

感谢您的阅读。

No one has answered the question:
Why is this concept confusing?

As an undergrad Computer Science major it took me awhile to understand this because of the way I read the code.

The following is not correct!


x = y++

X is equal to y post increment. Which would logically seem to mean X is equal to the value of Y after the increment operation is done. Post meaning after.

or

x = ++y
X is equal to y pre-increment. Which would logically seem to mean X is equal to the value of Y before the increment operation is done. Pre meaning before.


The way it works is actually the opposite. This concept is confusing because the language is misleading. In this case we cannot use the words to define the behavior.
x=++y is actually read as X is equal to the value of Y after the increment.
x=y++ is actually read as X is equal to the value of Y before the increment.

The words pre and post are backwards with respect to semantics of English. They only mean where the ++ is in relation Y. Nothing more.

Personally, if I had the choice I would switch the meanings of ++y and y++. This is just an example of a idiom that I had to learn.

If there is a method to this madness I'd like to know in simple terms.

Thanks for reading.

_畞蕅 2024-10-15 07:13:11

这很简单。两者都会增加变量的值。以下两行是相同的:

x++;
++x;

区别在于您是否使用递增的变量值:

x = y++;
x = ++y;

这里,两行都将 y 的值递增 1。然而,第一个将增量之前的 y 值赋给 x,第二个将增量之后的 y 值赋给 x。

因此,只有当增量也用作表达式时才会有区别。后置增量在返回值后递增。预增量先于增量。

It's pretty simple. Both will increment the value of a variable. The following two lines are equal:

x++;
++x;

The difference is if you are using the value of a variable being incremented:

x = y++;
x = ++y;

Here, both lines increment the value of y by one. However, the first one assigns the value of y before the increment to x, and the second one assigns the value of y after the increment to x.

So there's only a difference when the increment is also being used as an expression. The post-increment increments after returning the value. The pre-increment increments before.

终陌 2024-10-15 07:13:11
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 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

Post increment implies the value i is incremented after it has been assigned to k. However, pre increment implies the value j is incremented before it is assigned to l.

The same applies for decrement.

神魇的王 2024-10-15 07:13:11

后自增:

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.

Post-increment:

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.

Pre-increment:

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.
愿与i 2024-10-15 07:13:11

这里已经有了很好的答案,但像往常一样,仅仅记住这些工作的方式似乎普遍缺乏清晰度。我想这是因为从语义上解决命名法并不完全简单。例如,您可能知道“pre-”的意思是“之前”。但是预自增 ++i 是返回自增之前 i 的值,还是在返回值之前自增 i 呢?

我发现从左到右直观地跟踪表达式要容易得多:

        ++                    i 
-------------------------------------------------->
    Increment i   Then supply the value of i


             i                      ++
-------------------------------------------------->
    Supply the value of i    Then increment i

当然,正如阿尔夫在接受的答案中指出的那样,这可能不会反映“真实的我”何时更新,但这是一种方便的思考方式提供给表达式的内容。

Already good answers here, but as usual there seems to be some general lack of clarity in simply remembering which way round these work. I suppose this arises because semantically resolving the nomenclature is not entirely straightforward. For example, you may be aware that "pre-" means "before". But does the pre-increment ++i return the value of i before the increment, or does it increment i before returning a value?

I find it much easier to visually follow the expression through from left to right:

        ++                    i 
-------------------------------------------------->
    Increment i   Then supply the value of i


             i                      ++
-------------------------------------------------->
    Supply the value of i    Then increment i

Of course, as Alf points out in the accepted answer, this may not reflect when the 'real i' is updated, but it is a convenient way of thinking about what gets supplied to the expression.

白况 2024-10-15 07:13:11

既然我们现在有了内联 JavaScript 片段,我不妨添加一个 pre 和 pos 增量的交互式示例。它不是 C++,但概念保持不变。

let A = 1;
let B = 1;

console.log('A++ === 2', A++ === 2);
console.log('++B === 2', ++B === 2);

Since we now have inline javascript snippets I might as well add an interactive example of pre and pos increment. It's not C++ but the concept stays the same.

let A = 1;
let B = 1;

console.log('A++ === 2', A++ === 2);
console.log('++B === 2', ++B === 2);

梦中的蝴蝶 2024-10-15 07:13:11

来自 C99 标准(C++ 应该是相同的,除非奇怪的重载)

6.5.2.4 后缀递增和递减运算符

约束

1 后缀增量的操作数
或减量运算符应具有
合格或不合格的真实或
指针类型并且应该是可修改的
左值。

语义

2 后缀++的结果
运算符是操作数的值。
得到结果后,
操作数的值递增。
(即,值 1
添加适当的类型。)参见
加性算子的讨论
和复合赋值
有关约束、类型和的信息
转换和影响
对指针的操作。侧面
更新存储值的效果
操作数应出现在
上一个和下一个序列点。

3 后缀 -- 运算符是类似的
到后缀 ++ 运算符,除了
操作数的值为
递减(即,值 1
减去适当的类型
来自它)。

6.5.3.1 前缀递增和递减运算符

约束

1 前缀增量的操作数
或减量运算符应具有
合格或不合格的真实或
指针类型并且应该是可修改的
左值。

语义

2 操作数的值
前缀 ++ 运算符递增。这
结果是操作数的新值
增量后。表达式
++E 等价于(E+=1)。请参阅加性运算符的讨论和
复合作业的信息
约束、类型、副作用和
转换和影响
对指针的操作。

3 前缀 -- 运算符是类似的
前缀 ++ 运算符,除了
操作数的值为
递减。

From the C99 standard (C++ should be the same, barring strange overloading)

6.5.2.4 Postfix increment and decrement operators

Constraints

1 The operand of the postfix increment
or decrement operator shall have
qualified or unqualified real or
pointer type and shall be a modifiable
lvalue.

Semantics

2 The result of the postfix ++
operator is the value of the operand.
After the result is obtained, the
value of the operand is incremented.
(That is, the value 1 of the
appropriate type is added to it.) See
the discussions of additive operators
and compound assignment for
information on constraints, types, and
conversions and the effects of
operations on pointers. The side
effect of updating the stored value of
the operand shall occur between the
previous and the next sequence point.

3 The postfix -- operator is analogous
to the postfix ++ operator, except
that the value of the operand is
decremented (that is, the value 1 of
the appropriate type is subtracted
from it).

6.5.3.1 Prefix increment and decrement operators

Constraints

1 The operand of the prefix increment
or decrement operator shall have
qualified or unqualified real or
pointer type and shall be a modifiable
lvalue.

Semantics

2 The value of the operand of the
prefix ++ operator is incremented. The
result is the new value of the operand
after incrementation. The expression
++E is equivalent to (E+=1). See the discussions of additive operators and
compound assignment for information on
constraints, types, side effects, and
conversions and the effects of
operations on pointers.

3 The prefix -- operator is analogous
to the prefix ++ operator, except that
the value of the operand is
decremented.

拔了角的鹿 2024-10-15 07:13:11

后增量(a++)

如果
int b = a++,那么这意味着

int b = a;

a = a+1;

这里我们将值加1。该值在增量之前返回,

例如 a = 1; b = a++;

那么 b=1 和 a=2

预自增 (++a)

If int b = ++a;那么这意味着

a=a+1;

int b=a ;

预增量:这将为主值加 1。增加后返回值,对于a = 1; b = ++a;
那么b=2并且a=2。

Post increment(a++)

If
int b = a++,then this means

int b = a;

a = a+1;

Here we add 1 to the value. The value is returned before the increment is made,

For eg a = 1; b = a++;

Then b=1 and a=2

Pre-increment (++a)

If int b = ++a; then this means

a=a+1;

int b=a ;

Pre-increment: This will add 1 to the main value. The value will be returned after the increment is made, For a = 1; b = ++a;
Then b=2 and a=2.

晨曦慕雪 2024-10-15 07:13:11
#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
}

使用指针进行后置和前置递增

#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
}

Post and Pre Increment with Pointers

鸢与 2024-10-15 07:13:11

预增量是在增量值 ++ 之前 例如:

(++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

The pre increment is before increment value ++ e.g.:

(++v) or 1 + v

The post increment is after increment the value ++ e.g.:

(rmv++) or rmv + 1

Program:

int rmv = 10, vivek = 10;
cout << "rmv++ = " << rmv++ << endl; // the value is 10
cout << "++vivek = " << ++vivek; // the value is 11
雪化雨蝶 2024-10-15 07:13: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++ 
)

You should also be aware that the behaviour of postincrement/decrement operators is different in C/C++ and Java.

Given

  int a=1;

in C/C++ the expression

 a++ + a++ + a++

evaluates to 3, while in Java it evaluates to 6. Guess why...

This example is even more confusing:

cout << a++ + a++ + a++ << "<->" << a++ + a++ ;

prints 9<->2 !! This is because the above expression is equivalent to:

operator<<( 
  operator<<( 
    operator<<( cout, a++ + a++ ), 
    "<->"
  ), 
  a++ + a++ + a++ 
)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文