增量、前增量和后增量

发布于 2025-01-06 06:40:03 字数 443 浏览 2 评论 0原文

请帮我解决这个问题。该表达式遵循的步骤是:

//Expression
offSpring1[m1++] = temp1;

//步骤:

1.- 增加 m1

2.- 将 temp1 分配给 offSpring

我一直认为括号内的表达式是首先要做的。但现在我很困惑。所以如果这样写:

//Expression
offSpring1[++m1] = temp1;
//步骤是:

1.- 将 temp1 分配给 offSpring
2.- 增加 m1

如果步骤与第一个相同,那么 i++ 和 ++i 之间有什么区别?

Help me to resolve this please. The steps that follows that expressions are:

//Expression
offSpring1[m1++] = temp1;

//Steps:

1.- increment m1

2.- assign temp1 to offSpring

I have always thought that the expression inside the brackets was the first to be done. But now I am confuse. So if a write this:

//Expression
offSpring1[++m1] = temp1;
//Steps would be:

1.- assign temp1 to offSpring
2.- increment m1

If the steps would be the same as first ones, what is the difference between i++ and ++i?

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

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

发布评论

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

评论(10

你与清晨阳光 2025-01-13 06:40:03
int i = 0;
std::cout << i++ << std::endl;
std::cout << i << "\nreset" << std::endl;
i = 0;
std::cout << ++i << std::endl;
std::cout << i << std::endl;

输出:

0
1
reset
1
1

i++ 返回表达式中当前的值,然后递增变量。
++i 将递增变量,然后返回要在当前表达式中使用的值。

int i = 0;
std::cout << i++ << std::endl;
std::cout << i << "\nreset" << std::endl;
i = 0;
std::cout << ++i << std::endl;
std::cout << i << std::endl;

output:

0
1
reset
1
1

i++ returns the value as it currently stands in the expression, then increments the variable.
++i will increment the variable, then return the value to use in the current expression.

泼猴你往哪里跑 2025-01-13 06:40:03
offSpring1[m1++] = temp1;

offSpring1[m1] = temp1;
m1 += 1;

并且

offSpring1[++m1] = temp1;

m1 += 1;
offSpring1[m1] = temp1;
offSpring1[m1++] = temp1;

is

offSpring1[m1] = temp1;
m1 += 1;

and

offSpring1[++m1] = temp1;

is

m1 += 1;
offSpring1[m1] = temp1;
一杆小烟枪 2025-01-13 06:40:03
  • j = ++ii = i+1 相同; j = i;
  • j = i++j = i; 相同我=我+1;
  • j = ++i is the same as i = i+1; j = i;
  • j = i++ is the same as j = i; i = i+1;
多像笑话 2025-01-13 06:40:03

只需运行这两个不同的测试程序即可了解后自增和预自增运算符之间的差异

对于 ++i(前自增)

int main()
{
    int* offSpring = calloc(20,sizeof(int));
    int m1 =1;
    offSpring[++m1] = 10;
    printf("%d,%d",offSpring[m1],m1);
}

在第一个程序中,您将得到 10 作为值关闭弹簧[m1]。
为什么?因为这是预递增运算符,这意味着第一个 m1 递增,其余的进行评估。

对于 i++(后增量)

int main()
{
    int* offSpring = calloc(20,sizeof(int));
    int m1 =1;
    offSpring[m1++] = 10;
    printf("%d,%d",offSpring[m1],m1);
}

在第二个中,因为使用了后增量运算符,您将得到 0 值,因为您首先将 10 分配给 offSpring[m1],然后 m1 递增。

Just run these two different test programs to understand the difference between the post-increment and the pre-increment operators

For ++i (pre-increment)

int main()
{
    int* offSpring = calloc(20,sizeof(int));
    int m1 =1;
    offSpring[++m1] = 10;
    printf("%d,%d",offSpring[m1],m1);
}

In the first one you will get 10 as the value of offSpring[m1].
Why? Because this is the pre-increment operator which means that first m1 gets incremented and the the rest gets evaluated.

For i++(post-increment)

int main()
{
    int* offSpring = calloc(20,sizeof(int));
    int m1 =1;
    offSpring[m1++] = 10;
    printf("%d,%d",offSpring[m1],m1);
}

In the second because the post-increment operator is used you will get a 0 value since you are first assigning 10 to offSpring[m1] and then m1 gets incremented.

池木 2025-01-13 06:40:03

offSpring1[m1++] = temp1; 不执行您所说的操作。

  1. 指定 temp_m1 = m1。
  2. 增量 m1。
  3. 索引 offSpring1[temp_m1]
  4. temp1 分配给索引值。

另一方面,offSpring1[++m1] = temp1; 的工作原理如下:

  1. 递增 m1。
  2. index offSpring1[m1]
  3. temp1 分配给索引值。

offSpring1[m1++] = temp1; doesn't do what you said.

  1. assign temp_m1 = m1.
  2. increment m1.
  3. index offSpring1[temp_m1]
  4. assign temp1 into indexed value.

On the other hand offSpring1[++m1] = temp1; works like this:

  1. increment m1.
  2. index offSpring1[m1]
  3. assign temp1 into indexed value.
一花一树开 2025-01-13 06:40:03

尽管后缀增量是第一个示例中第一个被评估的,但它的值是被增量的变量的原始值。

offSpring1[m1++] = temp1;

因此,即使 m1 在数组索引之前递增,temp1 的值也会分配到位置 m1 - 1 处。

Even though postfix increment is the first to be evaluated in your first example, its value is the original value of the variable being incremented.

offSpring1[m1++] = temp1;

So even though m1 is incremented before array idexing, the value of temp1 is assigned at position m1 - 1.

心病无药医 2025-01-13 06:40:03

表达式(或子表达式)有两个方面:它的值,
及其副作用。 i++的值就是i的值;这
++ i 的值是值 i + 1,转换为 i 的类型。
这是表达式中使用的值。两者的副作用是
增加变量i。这可能发生在
前面的序列点和下一个序列点之前。假设 i 是一个全局变量
变量,并且您编写如下内容:

i = 0;
f()[i ++] = g();
f()[++ i] = g();

标准没有说明 i 的值是否在 f() 中出现
g() 是增量之前或之后。在这两种情况下。
标准所说的只是增量的效果将
发生在完整表达式开始之后(但也许作为
完整表达中的第一件事)和结束之前。 (还有那个
它们不会与函数调用交错,因此 if f()
读取 i 两次,保证看到相同的值。)

There are two aspects to an expression (or sub-expression): its value,
and its side effects. The value of i ++ is the value of i; the
value of ++ i is the value i + 1, converted to the type of i.
This is the value used in the expression. The side effects of both is
to increment the variable i. This may occur at any time after the
preceding sequence point and before the next. Supposing i is a global
variable, and you write something like:

i = 0;
f()[i ++] = g();
f()[++ i] = g();

The standard says nothing about whether the value of i seen in f()
or g() is that before the incrementation, or after. In neither case.
All the standard says is that the effects of the incrementation will
take place after the start of the full expression (but perhaps as the
first thing in the full expression) and before the end of it. (And that
they won't be interleaved with a function call, so that if f()
reads i twice, it is guaranteed to see the same value.)

深陷 2025-01-13 06:40:03

不幸的是,在您发布的那两个代码片段中,没有保证评估的顺序。如果你的表达不恰当,或多或少就会发生什么事情。

首先从 a++ 和 ++a 之间的区别开始:

  • a++ 会递增 a,但使用它的表达式将在递增之前看到 a 的值
  • ++a 将递增 a,并且使用它的表达式将看到递增后的值。

列表

buffer[a++] = b;

编译器可以决定在表达式中的任何点执行 ++ 的 。因此,如果“b”实际上是涉及 a 的表达式,则可以在不同的编译器上得到不同的结果。以下两者都是有效的:

  • 获取 a 的值;
  • 递增 a
  • 计算其中 buffer[old value] 指向
  • 评估 b
  • store b

或 this

  • 评估 b;
  • 计算出 buffer[a] 指向
  • 存储 b
  • 增量 a 的

位置,如果 'b' 碰巧涉及 a,这两种实现将产生不同的结果。两者都有效。

Unfortunately, in those 2 code snippets you've posted there, there's no guaranteed order of evaluation. If your expressions are inappropriate, more or less anything could happen.

To start with the difference between a++ and ++a:

  • a++ will increment a but the expression using it will see the value of a before the increment
  • ++a will increment a, and the expression using it will see the incremented value.
  • List item

with

buffer[a++] = b;

the compiler can decide to do the ++ at any point within the expression. Thus if 'b' is actually an expression involving a, you can get different results on different compilers. Both of the following would be valid:

  • get the value of a;
  • increment a
  • work out where buffer[old value] points to
  • evaluate b
  • store b

or this

  • evaluate b;
  • work out where buffer[a] points to
  • store b
  • increment a

if 'b' should happen to involve a, those 2 implementations would produce different results. Both are valid.

缪败 2025-01-13 06:40:03

它的工作原理与您所描述的完全相反:

offSpring1[m1++] = temp1
offSpring[m1] = temp1; m1 = m1 + 1;

OffSpring1[++m1] = temp1
m1 = m1 + 1; OffSpring1[m1] = temp1;

在计算表达式之前前缀表示法递增
计算表达式后后缀表示法递增

It works precisely the opposite of what you described:

offSpring1[m1++] = temp1 is the same as
offSpring[m1] = temp1; m1 = m1 + 1;

OffSpring1[++m1] = temp1 is the same as
m1 = m1 + 1; OffSpring1[m1] = temp1;

Prefix notation increments before evaluating the expression
Postfix notation increments after evaluating the expression

谁的新欢旧爱 2025-01-13 06:40:03

第一个的描述是第二个的正确描述。第一个的正确描述非常相似,您只需要在其他步骤之前添加“复制 m1 的当前值”步骤即可。

但是,如果 m1 具有原始类型,那么这里确实明显缺乏序列点。 C++03 和 C++11 之间的规则略有变化。

如果m1具有用户定义的类型,则涉及影响排序的函数调用。


此代码

offSpring1[m1++] = temp1;

执行以下操作(如果 m1 是基本类型):

auto const old_m1(m1);
auto const new_m1(old_m1 + 1);
auto& lhs(offSpring[old_m1]);
parallel { lhs = temp1; m1 = new_m1; }

此代码

offSpring1[++m1] = temp1;

完全相同,只是 lhs 使用 new_m1 绑定,而不是使用 new_m1 old_m1

无论哪种情况,都未指定 lhs 是写入 m1 之前还是之后。

如果 m1 不是原始类型,它看起来更像:

auto const& index = m1.operator++(0); // one argument
auto& lhs = offSpring.operator[](index);
lhs = temp1;

vs

auto const& index = m1.operator++(); // no arguments
auto& lhs = offSpring.operator[](index);
lhs = temp1;

在这两种情况下,对 m1 的更改肯定是在写入 lhs.

The description of the first is the correct description for the second. The correct description of the first is very similar, you just need a "copy current value of m1" step added before the others.

But you do have a distinct lack of sequence points here, if m1 has a primitive type. The rules change somewhat between C++03 and C++11.

If m1 has a user-defined type, then there are function calls involved which influence sequencing.


This code

offSpring1[m1++] = temp1;

performs the following (if m1 is a primitive type):

auto const old_m1(m1);
auto const new_m1(old_m1 + 1);
auto& lhs(offSpring[old_m1]);
parallel { lhs = temp1; m1 = new_m1; }

This code

offSpring1[++m1] = temp1;

is exactly the same except that lhs is bound using new_m1 instead of old_m1.

In either case, it is unspecified whether lhs is written to before or after m1.

If m1 is not a primitive type, it looks more like:

auto const& index = m1.operator++(0); // one argument
auto& lhs = offSpring.operator[](index);
lhs = temp1;

vs

auto const& index = m1.operator++(); // no arguments
auto& lhs = offSpring.operator[](index);
lhs = temp1;

In both these cases, the change to m1 is definitely made before the write to lhs.

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