В чем разница между ++i и i++?

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

22 ответа

Решение
  • ++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 кажется более распространенным, возможно, потому что это то, что используется в K & R.

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

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

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

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

i++ известен как Post Increment, тогда как ++i называется Pre Increment.

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: - В этом сценарии сначала выполняется приращение, а затем присваивается значение

Ниже приведена визуализация изображения, а также хорошее практическое видео ( http://www.youtube.com/watch?v=lrtcfgbUXm4), которое демонстрирует то же самое.

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

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

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

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

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

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

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

#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 будет иметь увеличенное значение.


заголовок

Когда возвращаемое значение нигде не сохраняется, разницы нет. Классическим примером является синтаксис цикла for:

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

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

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

Правило помнить

Чтобы не путать два оператора, я стараюсь принять это правило:

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

Сказал другими словами:

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

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

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

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

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

Тем не менее, вы должны рассмотреть две основные проблемы с предыдущей логикой.

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

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

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

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

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

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

Пример:

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

++ я предварительно инкрементный другой пост-инкремент

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 ++ (операция Postfix): присваивает, а затем увеличивает значение
(например): int i = 5, int b = i++
В этом случае 5 назначается сначала b, а затем увеличивается до 6 и так далее.

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

я ++ и ++ я

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

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;

// Операторы приращения

я = 1;

j = ++ i; // я теперь 2, j тоже 2

j = i ++; // я сейчас 3, j 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++ post/pre-инкремент переменной указателя

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

Проще говоря, разница между ними заключается в шагах. Взгляните на изображение ниже.

Пример:

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

Результат 1

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

The jрезультат

Примечание: в обоих случаях iзначения 2

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

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

Функция (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

Главное отличие

  • i++ Post(после увеличения) и
  • ++ я Pre (до приращения)

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

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

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

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

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

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;

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

// case 1 :

i++;

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

// case 2

++i;

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

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

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

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

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

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

Другие вопросы по тегам