В чем разница между ++ i и i ++? - PullRequest
764 голосов
/ 24 августа 2008

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

Ответы [ 21 ]

947 голосов
/ 24 августа 2008
  • ++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++() является функцией, и компилятор не может знать, как оптимизировать создание временного объекта для хранения промежуточного значения.

155 голосов
/ 28 марта 2012

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 будет присвоено 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.

37 голосов
/ 20 сентября 2008

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

31 голосов
/ 24 августа 2008

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

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

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

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

23 голосов
/ 25 июля 2013

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

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

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

enter image description here

20 голосов
/ 24 августа 2008

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

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

13 голосов
/ 07 мая 2011

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

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

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

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

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

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

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

12 голосов
/ 19 февраля 2018

Они оба увеличивают число. ++ 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
6 голосов
/ 17 сентября 2013

++ 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
6 голосов
/ 13 мая 2016

++ 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. Но в зависимости от логики вашей программы оно может варьироваться.

...