在C语言中,使用++i和i++之间的区别是什么,在for循环的增量块中应该使用哪个?


++i增加值,然后返回该值。

i++返回值,然后使其递增。

这是一个微妙的区别。

对于For循环,使用++i,因为它稍微快一些。i++将创建一个被丢弃的额外副本。


++i将增加i的值,然后返回增加后的值。 I = 1; J = ++i; (i = 2, j = 2) i++将增加I的值,但返回I被增加前的原始值。 I = 1; J = i++; (i = 2, j = 1)

对于For循环,两者都可以。++i似乎更常见,也许是因为这是K&R中使用的。

在任何情况下,遵循“优先选择++i而不是i++”的指导方针,您都不会出错。

这里有一些关于++i和i++的效率的评论。在任何非学生项目的编译器中,都不会有性能差异。您可以通过查看生成的代码来验证这一点,它们是相同的。

效率问题很有趣……以下是我试图回答的问题: 在C语言中i++和++i之间有性能差异吗?

正如@OnFreund指出的那样,对于c++对象是不同的,因为操作符++()是一个函数,编译器不知道优化掉一个临时对象的创建来保存中间值。


++i可以比i++稍微快一点的原因是,i++可以在i的值被递增之前要求它的本地副本,而++i从不这样做。在某些情况下,一些编译器会尽可能地优化它……但这并不总是可能的,并不是所有编译器都这样做。

我尽量不太依赖编译器优化,所以我会遵循Ryan Fox的建议:当我可以使用两者时,我会使用++ I。


请不要担心哪个“效率”(真的是速度)更快。现在我们有编译器来处理这些事情。使用任何一个有意义的,在此基础上更清楚地表明你的意图。


在循环中使用两者的有效结果是相同的。换句话说,循环将在两个实例中做完全相同的事情。

就效率而言,选择i++而不是++i可能会有一定的损失。根据语言规范,使用后增量操作符应该创建操作符所作用的值的额外副本。这可能是额外操作的来源。

但是,您应该考虑上述逻辑的两个主要问题。

Modern compilers are great. All good compilers are smart enough to realize that it is seeing an integer increment in a for-loop, and it will optimize both methods to the same efficient code. If using post-increment over pre-increment actually causes your program to have a slower running time, then you are using a terrible compiler. In terms of operational time-complexity, the two methods (even if a copy is actually being performed) are equivalent. The number of instructions being performed inside of the loop should dominate the number of operations in the increment operation significantly. Therefore, in any loop of significant size, the penalty of the increment method will be massively overshadowed by the execution of the loop body. In other words, you are much better off worrying about optimizing the code in the loop rather than the increment.

在我看来,整个问题可以归结为一种风格偏好。如果您认为预增量更具可读性,那么就使用它。就我个人而言,我更喜欢后增量,但这可能是因为这是我在了解优化之前学到的东西。

这是一个典型的过早优化的例子,像这样的问题有可能分散我们对设计中严肃问题的注意力。然而,这仍然是一个很好的问题,因为在“最佳实践”中没有统一的用法或共识。


我假设你现在已经理解了语义上的差异(尽管说实话我想知道为什么 人们会问“运算符X是什么意思”的问题,而不是阅读, 你知道的,一本书或网络教程之类的。

不管怎样,至于用哪个,忽略性能的问题 即使在c++中也不太重要。这是你做决定时应该遵循的原则 使用哪一种:

用代码表达你的意思。

如果语句中不需要value-before-increment,就不要使用这种形式的操作符。这是一个小问题,但除非你的风格指南禁止这样做 版本完全赞成其他的(又名愚蠢的风格指南),你应该使用 最准确地表达你要做的事情的形式。

QED,使用预增量版本:

for (int i = 0; i != X; ++i) ...

i++被称为后增量,而++ I被称为前增量。

i++

i++是后增量,因为它在操作结束后将I的值加1。

让我们看看下面的例子:

int i = 1, j;
j = i++;

这里j = 1,但i = 2。在这里,i的值将首先赋给j,然后i将增加。

++i

++i是预增量,因为它在操作之前将i的值加1。 它表示j = i;将在i++之后执行。

让我们看看下面的例子:

int i = 1, j;
j = ++i;

这里j = 2但是i = 2。这里i的值将在i增加i之后赋给j。 类似地,++i将在j=i;之前执行。

对于你的问题,在For循环的增量块中应该使用哪个?答案是,你可以用任何一个…没关系。它将执行相同次数的for循环。

for(i=0; i<5; i++)
   printf("%d ", i);

And

for(i=0; i<5; ++i)
   printf("%d ", i);

两个循环将产生相同的输出。也就是0 1 2 3 4。

重要的是你在哪里使用它。

for(i = 0; i<5;)
    printf("%d ", ++i);

在这种情况下,输出将是1 2 3 4 5。


A =i++表示A包含当前i的值。

A =++i表示A包含i的增量值。


i++:在这种情况下,首先赋值,然后进行递增。

++i:在这个场景中,首先完成增量,然后赋值

下面是图像可视化,这里也有一个很好的实用视频,演示了同样的。


:不久

++i和i++的工作原理是一样的,如果你不在函数中写它们的话。如果你使用function(i++)或function(++i),你可以看到区别。

函数(++i)表示首先将i增加1,然后将i放入具有新值的函数中。

Function (i++)表示在i加1之后将第一个i放入函数中。

int i=4;
printf("%d\n",pow(++i,2));//it prints 25 and i is 5 now
i=4;
printf("%d",pow(i++,2));//it prints 16 i is 5 now

++i:是增量前,另一个是增量后。

i++:获取元素,然后对其进行递增。 ++i:增加i,然后返回元素。

例子:

int i = 0;
printf("i: %d\n", i);
printf("i++: %d\n", i++);
printf("++i: %d\n", ++i);

输出:

i: 0
i++: 0
++i: 2

++i(前缀操作):递增,然后赋值 (例如):int I = 5, int b = ++ I 在这种情况下,先将6赋值给b,然后递增到7,依此类推。

i++(后缀操作):赋值,然后递增 (例如):int I = 5, int b = i++ 在这种情况下,5首先被赋值给b,然后增加到6,依此类推。

在for循环的情况下:i++主要用于,因为通常我们在for循环中递增之前使用i的起始值。但是根据您的程序逻辑,它可能会有所不同。


主要的区别是 i++ Post(After Increment)和 ++i Pre(增量前) Post if I =1,循环增量为1,2,3,4,n 如果I =1,循环会增加2 3 4 5 n


这种差异可以通过下面这段简单的c++代码来理解:

int i, j, k, l;
i = 1; //initialize int i with 1
j = i+1; //add 1 with i and set that as the value of j. i is still 1
k = i++; //k gets the current value of i, after that i is incremented. So here i is 2, but k is 1
l = ++i; // i is incremented first and then returned. So the value of i is 3 and so does l.
cout << i << ' ' << j << ' ' << k << ' '<< l << endl;
return 0;

预填充是指在同一行上的增量。后增量是指行执行后的增量。

int j = 0;
System.out.println(j); // 0
System.out.println(j++); // 0. post-increment. It means after this line executes j increments.

int k = 0;
System.out.println(k); // 0
System.out.println(++k); // 1. pre increment. It means it increments first and then the line executes

当它带有OR和AND操作符时,它变得更有趣。

int m = 0;
if((m == 0 || m++ == 0) && (m++ == 1)) { // False
    // In the OR condition, if the first line is already true
    // then the compiler doesn't check the rest. It is a
    // technique of compiler optimization
    System.out.println("post-increment " + m);
}

int n = 0;
if((n == 0 || n++ == 0) && (++n == 1)) { // True
    System.out.println("pre-increment " + n); // 1
}

在数组中

System.out.println("In Array");
int[] a = { 55, 11, 15, 20, 25 };
int ii, jj, kk = 1, mm;
ii = ++a[1]; // ii = 12. a[1] = a[1] + 1
System.out.println(a[1]); // 12

jj = a[1]++; // 12
System.out.println(a[1]); // a[1] = 13

mm = a[1]; // 13
System.out.printf("\n%d %d %d\n", ii, jj, mm); // 12, 12, 13

for (int val: a) {
     System.out.print(" " + val); // 55, 13, 15, 20, 25
}

在c++中,指针变量的后/前增量

#include <iostream>
using namespace std;

int main() {

    int x = 10;
    int* p = &x;

    std::cout << "address = " << p <<"\n"; // Prints the address of x
    std::cout << "address = " << p <<"\n"; // Prints (the address of x) + sizeof(int)
    std::cout << "address = " << &x <<"\n"; // Prints the address of x

    std::cout << "address = " << ++&x << "\n"; // Error. The reference can't reassign, because it is fixed (immutable).
}

下面的C代码片段说明了前后递增和递减操作符之间的区别:

int  i;
int  j;

增量运算符:

i = 1;
j = ++i;    // i is now 2, j is also 2
j = i++;    // i is now 3, j is 2

i++和++ I

这段小代码可能有助于从不同的角度来看待与已经发布的答案的差异:

int i = 10, j = 10;
  
printf ("i is %i \n", i);
printf ("i++ is %i \n", i++);
printf ("i is %i \n\n", i);
  
printf ("j is %i \n", j);
printf ("++j is %i \n", ++j);
printf ("j is %i \n", j);

结果是:

//Remember that the values are i = 10, and j = 10

i is 10 
i++ is 10     //Assigns (print out), then increments
i is 11 

j is 10 
++j is 11    //Increments, then assigns (print out)
j is 11 

注意之前和之后的情况。

for循环

至于在for循环的增量块中应该使用它们中的哪一个,我认为我们能做的最好的决定是使用一个很好的例子:

int i, j;

for (i = 0; i <= 3; i++)
    printf (" > iteration #%i", i);

printf ("\n");

for (j = 0; j <= 3; ++j)
    printf (" > iteration #%i", j);

结果是:

> iteration #0 > iteration #1 > iteration #2 > iteration #3
> iteration #0 > iteration #1 > iteration #2 > iteration #3 

我不知道你怎么想,但我没有看到它的用法有任何不同,至少在for循环中是这样。


你可以把它的内部转换看作是多条语句:

// case 1

i++;

/* you can think as,
 * i;
 * i= i+1;
 */



// case 2

++i;

/* you can think as,
 * i = i+i;
 * i;
 */

唯一的区别是变量的增量和运算符返回值之间的操作顺序不同。

这段代码及其输出解释了区别:

#include<stdio.h>

int main(int argc, char* argv[])
{
  unsigned int i=0, a;
  printf("i initial value: %d; ", i);
  a = i++;
  printf("value returned by i++: %d, i after: %d\n", a, i);
  i=0;
  printf("i initial value: %d; ", i);
  a = ++i;
  printf(" value returned by ++i: %d, i after: %d\n",a, i);
}

输出结果为:

i initial value: 0; value returned by i++: 0, i after: 1
i initial value: 0;  value returned by ++i: 1, i after: 1

所以基本上++i返回的值是在它被加1之后,而i++返回的值是在它被加1之前。最后,在这两种情况下,i的值都会增加。

另一个例子:

#include<stdio.h>

int main ()
  int i=0;
  int a = i++*2;
  printf("i=0, i++*2=%d\n", a);
  i=0;
  a = ++i * 2;
  printf("i=0, ++i*2=%d\n", a);
  i=0;
  a = (++i) * 2;
  printf("i=0, (++i)*2=%d\n", a);
  i=0;
  a = (i++) * 2;
  printf("i=0, (i++)*2=%d\n", a);
  return 0;
}

输出:

i=0, i++*2=0
i=0, ++i*2=2
i=0, (++i)*2=2
i=0, (i++)*2=0

很多时候是没有区别的

当返回值被赋给另一个变量时,或者当增量与应用操作优先级的其他操作一起执行时,差异很明显(i++*2不同于++i*2,以及(i++)*2和(++i)*2),在许多情况下它们是可互换的。一个经典的例子是for循环语法:

for(int i=0; i<10; i++)

有同样的效果吗

for(int i=0; i<10; ++i)

效率

预增量总是至少和后增量一样高效:事实上,后增量通常包括保留前一个值的副本,并可能添加一些额外的代码。

正如其他人所建议的,由于编译器优化很多次,它们同样有效,可能在这些情况下存在for循环。

要记住的规则

为了不混淆这两个运算符,我采用了下面的规则:

将运算符++相对于变量i的位置与++操作相对于赋值的顺序相关联

换言之:

++ before I表示必须在赋值之前进行递增; I之后的++表示必须在赋值之后进行递增:


简单地说,两者之间的区别在于步骤,请看下图。

例子:

int i = 1;
int j = i++;

j的结果是1

int i = 1;
int j = ++i;

j的结果是2

注意:在这两种情况下i的值都是2