Вопрос

В C, в чем разница между использованием ++i и i++, и который следует использовать в блоке приращения for петля?

Это было полезно?

Решение

  • ++i увеличит значение i, а затем верните увеличенное значение.

     i = 1;
     j = ++i;
     (i is 2, j is 2)
    
  • i++ увеличит значение i, но верните исходное значение, которое i удерживается перед увеличением.

     i = 1;
     j = i++;
     (i is 2, j is 1)
    

Для for цикл, либо работает. ++i кажется более распространенным, возможно, потому, что именно это используется в К&Р.

В любом случае следуйте принципу «предпочитайте ++i над i++"и вы не ошибетесь.

Есть пара замечаний по поводу эффективности ++i и i++.В любом компиляторе, не предназначенном для студенческих проектов, разницы в производительности не будет.Вы можете убедиться в этом, посмотрев на сгенерированный код, который будет идентичен.

Вопрос эффективности интересен...вот моя попытка ответить:Есть ли разница в производительности между i++ и ++i в C?

Как О Фройнде отмечает, что для объекта C++ все по-другому, поскольку operator++() это функция, и компилятор не может знать, как оптимизировать создание временного объекта для хранения промежуточного значения.

Другие советы

я++ известен как Сообщение приращения тогда как ++я называется Предварительный прирост.

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 будет назначен j после i приращение i.Сходным образом ++i будет выполнено раньше j=i;.

На ваш вопрос который следует использовать в блоке приращения цикла for? ответ: вы можете использовать любой..не имеет значения.Он выполнит ваш цикл for так же нет.раз.

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

И

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.

Пожалуйста, не беспокойтесь о «эффективности» (на самом деле скорости), какой из них быстрее.Сегодня у нас есть компиляторы, которые позаботятся об этих вещах.Используйте тот, который имеет смысл использовать, исходя из того, который более четко показывает ваши намерения.

++i увеличивает значение, а затем возвращает его.

i++ возвращает значение, а затем увеличивает его.

Это тонкая разница.

Для цикла for используйте ++i, так как это немного быстрее. i++ создаст дополнительную копию, которую просто выбрасывают.

i++:В этом сценарии сначала присваивается значение, а затем происходит его приращение.

++i:В этом сценарии сначала выполняется приращение, а затем присваивается значение.

Ниже представлена ​​визуализация изображения, а также вот хорошее практическое видео который демонстрирует то же самое.

enter image description here

Причина ++i может быть немного быстрее, чем i++ в том, что i++ может потребоваться локальная копия значения i, прежде чем оно будет увеличено, в то время как ++i никогда не делает.В некоторых случаях некоторые компиляторы, если это возможно, оптимизируют его...но это не всегда возможно, и не все компиляторы это делают.

Я стараюсь не слишком полагаться на оптимизацию компилятора, поэтому я бы последовал совету Райана Фокса:когда я могу использовать оба, я использую ++i.

Эффективный результат использования любого из них идентичен.Другими словами, цикл будет делать одно и то же в обоих случаях.

С точки зрения эффективности, выбор i++ вместо ++i может повлечь за собой штраф.С точки зрения спецификации языка, использование оператора постинкремента должно создавать дополнительную копию значения, над которым действует оператор.Это может быть источником дополнительных операций.

Однако вам следует учитывать две основные проблемы, связанные с предыдущей логикой.

  1. Современные компиляторы великолепны.Все хорошие компиляторы достаточно умны, чтобы понимать, что они видят целочисленное приращение в цикле for, и оптимизируют оба метода до одного и того же эффективного кода.Если использование пост-инкремента вместо предварительного приращения фактически приводит к замедлению времени выполнения вашей программы, то вы используете ужасный компилятор.

  2. С точки зрения оперативной сложности эти два метода (даже если копирование действительно выполняется) эквивалентны.Количество инструкций, выполняемых внутри цикла, должно значительно доминировать над количеством операций в операции приращения.Следовательно, в любом цикле значительного размера последствия метода приращения будут значительно омрачены выполнением тела цикла.Другими словами, вам гораздо лучше беспокоиться об оптимизации кода в цикле, а не о приращении.

На мой взгляд, весь вопрос сводится просто к предпочтениям стиля.Если вы считаете, что преинкремент более читабелен, используйте его.Лично я предпочитаю постинкремент, но, вероятно, это потому, что меня этому научили еще до того, как я узнал что-либо об оптимизации.

Это типичный пример преждевременной оптимизации, и подобные проблемы могут отвлечь нас от серьезных проблем проектирования.Однако этот вопрос по-прежнему стоит задать, поскольку в отношении «лучшей практики» нет единообразия в использовании или консенсуса.

Они оба увеличивают число. ++i эквивалентно i = i + 1.

i++ и ++i очень похожи, но не совсем одинаковы.Оба увеличивают число, но ++i увеличивает число перед вычислением текущего выражения, тогда как i++ увеличивает число после вычисления выражения.

Пример:

int i = 1;
int x = i++; //x is 1, i is 2
int y = ++i; //y is 3, i is 3

++i (Операция префикса):Увеличивает, а затем присваивает значение
(например): int i = 5, int b = ++iВ этом случае 6 сначала присваивается значению b, затем увеличивается до 7 и так далее.

i++ (Постфиксная операция):Назначает, а затем увеличивает значение
(например): int i = 5, int b = i++В этом случае 5 сначала присваивается значению b, а затем увеличивается до 6 и так далее.

В случае цикла for: i++ в основном используется, потому что обычно мы используем начальное значение i перед увеличением цикла for.Но в зависимости от логики вашей программы она может отличаться.

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

Я предполагаю, что вы понимаете разницу в семантике сейчас (хотя, честно говоря, мне интересно, почему люди спрашивают, что означает «Оператор X» означает «вопросы переполнения стека, а не чтение, вы знаете, книгу или веб -учебник или что -то в этом роде.

Но в любом случае, насколько можно использовать, игнорируйте вопросы производительности, которые маловероятно важны даже в C ++.Это принцип, который вы должны использовать при принятии решения о том, что использовать:

Скажите, что вы имеете в виду в коде.

Если вам не требуется приращение значения до приращения в вашем операторе, не используйте эту форму оператора.Это небольшая проблема, но если вы не работаете с руководством по стилю, которое полностью запрещает одну версию в пользу другой (иначе, руководство по стилю кости), вы должны использовать форму, которая наиболее точно выражает то, что вы пытаетесь сделать.

QED, используйте версию до приращения:

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

Разницу можно понять с помощью этого простого кода 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;

Основное отличие

  • я++ Сообщение(После приращения) и
  • ++я Pre (До приращения)

    • опубликуй, если i =1 цикл увеличивается как 1,2,3,4,n
    • предварительно, если i =1 цикл увеличивается как 2,3,4,5,n

я++ и ++я

Этот небольшой код может помочь визуализировать разницу под другим углом, чем уже опубликованные ответы:

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, я думаю, что лучшее, что мы можем сделать для принятия решения, — это использовать хороший пример:

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.

Следующий фрагмент кода 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

Прекремент означает увеличение в той же строке.Постинкремент означает приращение после выполнения строки.

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 OR condition if first line is already true then compiler doesn't check the rest. It is 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 address of x
    std::cout<<"address = "<<p<<"\n"; //prints (address of x) + sizeof(int)
    std::cout<<"address = "<<&x<<"\n"; //prints address of x

    std::cout<<"address = "<<++&x<<"\n"; //error. reference can't re-assign because it is fixed (immutable)
}

Вкратце:

++i и i++ работает так же, если вы не пишете их в функции.Если вы используете что-то вроде function(i++) или function(++i) вы можете увидеть разницу.

function(++i) говорит: сначала увеличьте i на 1, после этого поместите это i в функцию с новым значением.

function(i++) говорит, поставь сначала i в функцию после этого приращения i на 1.

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

Единственная разница заключается в порядке операций между приращением переменной и значением, возвращаемым оператором.

Этот код и его вывод объясняют разницу:

#include<stdio.h>

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

Выход:

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

Так что в основном ++i возвращает значение после его увеличения, а ++i вернуть значение до его увеличения.В итоге в обоих случаях 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=2

Много раз нет никакой разницы

Различия очевидны, когда возвращаемое значение присваивается другой переменной или когда приращение выполняется в сочетании с другими операциями, где применяется приоритет операций (i++*2 отличается от ++i*2, но (i++)*2 и (++i)*2 возвращает одно и то же значение) во многих случаях они взаимозаменяемы.Классическим примером является синтаксис цикла for:

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

имеет тот же эффект

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

Правило, которое следует запомнить

Чтобы не создавать путаницы между двумя операторами, я принял следующее правило:

Связать должность оператора ++ относительно переменной i по заказу ++ операция по заданию

Другими словами:

  • ++ до i означает, что необходимо выполнить приращение до назначение;
  • ++ после i означает, что необходимо выполнить приращение после назначение:

Вы можете думать о внутреннем преобразовании этого как о несколько утверждений;

// case 1 :

i++;

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

// case 2

++i;

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

a = i ++ означает, что A содержит ток I значение a = ++ i означает, что a содержит увеличенное значение i

Вот пример, чтобы понять разницу

int i=10;
printf("%d %d",i++,++i);

выход: 10 12/11 11 (в зависимости от порядка оценки аргументов printf функция, которая варьируется в зависимости от компилятора и архитектуры)

Объяснение:i++->i печатается, а затем увеличивается.(Печатает 10, но i станет 11)++i->i value увеличивает и печатает значение.(Печатает 12 и значение i также 12)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top