В C, в чем разница между использованием ++i
и i++
, и что следует использовать в блоке приращения for
цикла?
c
for-loop
post-increment
pre-increment
The.Anti.9
источник
источник
Ответы:
++i
будет увеличивать значениеi
, а затем возвращать увеличенное значение.i++
будет увеличивать значениеi
, но возвращать исходное значение, котороеi
удерживалось до увеличения.Для
for
цикла либо работает.++i
кажется более распространенным, может быть , потому что это то , что используется в K & R .В любом случае, следуйте указаниям «предпочитайте
++i
болееi++
», и вы не ошибетесь.Есть пара комментариев относительно эффективности
++i
иi++
. В любом компиляторе не для студенческого проекта разницы в производительности не будет. Вы можете убедиться в этом, посмотрев на сгенерированный код, который будет идентичен.Вопрос эффективности интересен ... вот моя попытка ответить: есть ли разница в производительности между i ++ и ++ i в C?
Как отмечает @OnFreund , он отличается для объекта C ++, поскольку
operator++()
это функция, и компилятор не может знать, как оптимизировать создание временного объекта для хранения промежуточного значения.источник
for(int i=0; i<10; i++){ print i; }
не будет ли это отличаться отfor(int i=0; i<10; ++i){ print i; }
моего понимания того, что некоторые языки будут давать разные результаты в зависимости от того, что вы используете.i++
потому что он имеет форму «операнд-оператор», а именно присваивание «операнд-оператор-значение». Другими словами, целевой операнд находится в левой части выражения, как и в операторе присваивания.i++
иprint i
есть в разных утверждениях, а потому, чтоi++;
иi<10
есть. Замечание @ jonnyflash не совсем так. Предположим, у вас естьfor(int i=0; i++<10){ print i; }
иfor(int i=0; ++i<10){ print i; }
. Они будут работать по-другому, как описано @johnnyflash в первом комментарии.i ++ известен как Post Increment, тогда как ++ i называется Pre Increment.
i++
i++
это постинкремент, потому что он увеличиваетi
значение на 1 после завершения операции.Давайте посмотрим на следующий пример:
Здесь ценность
j = 1
ноi = 2
. Здесь значениеi
будет присвоеноj
первому, а затемi
будет увеличено.++i
++i
является предварительным приращением, потому что оно увеличиваетi
значение на 1 перед операцией. Значитj = i;
выполнится послеi++
.Давайте посмотрим на следующий пример:
Здесь ценность
j = 2
ноi = 2
. Здесь значениеi
будет присвоеноj
послеi
увеличенияi
. Аналогично++i
будет выполнен раньшеj=i;
.На ваш вопрос, который следует использовать в блоке инкремента цикла for? Ответ в том, что вы можете использовать любой ... не имеет значения. Он выполнит ваш цикл for же нет. раз.
А также
Оба цикла будут давать одинаковый результат. то есть
0 1 2 3 4
.Это имеет значение только там, где вы его используете.
В этом случае вывод будет
1 2 3 4 5
.источник
Пожалуйста, не беспокойтесь о «эффективности» (скорости, действительно) которой быстрее. В наши дни у нас есть компиляторы, которые заботятся об этих вещах. Используйте тот, который имеет смысл использовать, исходя из того, что более четко показывает ваши намерения.
источник
operator++(int)
(постфиксная версия) код должен создать временный объект, который будет возвращен. Вы уверены, что компиляторы всегда могут это оптимизировать?++i
увеличивает значение, затем возвращает его.i++
возвращает значение, а затем увеличивает его.Это тонкая разница.
Для цикла for используйте
++i
, так как он немного быстрее.i++
создаст дополнительную копию, которую просто выбрасывают.источник
i++
: В этом сценарии сначала присваивается значение, а затем происходит приращение.++i
: В этом сценарии сначала выполняется приращение, а затем присваивается значениеНиже приведена визуализация изображения, а также хорошее практическое видео, демонстрирующее то же самое.
источник
Причина
++i
может быть немного быстрее, чем вi++
том, чтоi++
может потребоваться локальная копия значения i, прежде чем оно будет увеличено, хотя++i
никогда этого не происходит. В некоторых случаях некоторые компиляторы будут оптимизировать его, если это возможно ... но это не всегда возможно, и не все компиляторы делают это.Я стараюсь не слишком полагаться на оптимизацию компиляторов, поэтому следую совету Райана Фокса: когда я могу использовать оба, я использую
++i
.источник
i
чем значение 1, когда вы пишете оператор1;
.Эффективный результат использования любого в цикле идентичен. Другими словами, цикл будет делать одинаковую вещь в обоих случаях.
С точки зрения эффективности, выбор i ++ вместо ++ i может быть наказан. С точки зрения спецификации языка, использование оператора постинкремента должно создать дополнительную копию значения, на которое действует оператор. Это может быть источником дополнительных операций.
Тем не менее, вы должны рассмотреть две основные проблемы с предыдущей логикой.
Современные компиляторы великолепны. Все хорошие компиляторы достаточно умны, чтобы понимать, что в цикле for происходит целочисленный прирост, и он оптимизирует оба метода до одного и того же эффективного кода. Если использование постинкремента по сравнению с преинкрементом фактически приводит к замедлению работы вашей программы, то вы используете ужасный компилятор.
С точки зрения сложности во времени, эти два метода (даже если копия фактически выполняется) эквивалентны. Количество инструкций, выполняемых внутри цикла, должно значительно влиять на количество операций в операции приращения. Следовательно, в любом цикле значительного размера штраф за метод приращения будет значительно перекрыт выполнением тела цикла. Другими словами, вам лучше беспокоиться об оптимизации кода в цикле, а не о приращении.
На мой взгляд, весь вопрос просто сводится к стилевым предпочтениям. Если вы думаете, что предварительное увеличение более читабельно, используйте его. Лично я предпочитаю постинкремент, но это, вероятно, потому, что это было то, чему меня учили, прежде чем я что-то знал об оптимизации.
Это типичный пример преждевременной оптимизации, и подобные проблемы могут отвлечь нас от серьезных проблем в дизайне. Однако это все еще хороший вопрос, потому что в «наилучшей практике» нет единообразия в использовании или консенсусе.
источник
Они оба увеличивают число.
++i
эквивалентноi = i + 1
.i++
и++i
очень похожи, но не точно так же. Оба увеличивают число, но++i
увеличивают число до вычисления текущего выражения, тогда какi++
увеличивают число после вычисления выражения.Пример:
источник
++i
(Операция Префикса): приращения , а затем присваивает значение(например):
int i = 5
,int b = ++i
в этом случае, 6 назначаются б, а затем приращения до 7 и так далее.i++
(Операция Постфикса): Назначает , а затем увеличивает значение(например):
int i = 5
,int b = i++
в этом случае 5 назначаются б, а затем приращения до 6 и так далее.Incase для цикла for:
i++
в основном используется потому, что обычно мы используем начальное значениеi
перед увеличением цикла for. Но в зависимости от логики вашей программы это может варьироваться.источник
++i
: преинкрементный, другой постинкрементный.i++
: получает элемент, а затем увеличивает его.++i
: увеличивает i, а затем возвращает элемент.Пример:
Вывод:
источник
Я полагаю, вы понимаете разницу в семантике (хотя, честно говоря, мне интересно, почему люди задают вопросы «что означает оператор X» о переполнении стека, а не читают, вы знаете, книгу или веб-учебник или что-то в этом роде).
Но в любом случае, в отношении того, какой из них использовать, игнорируйте вопросы производительности, которые вряд ли важны даже в C ++. Это принцип, который вы должны использовать при принятии решения, какой:
Скажите, что вы имеете в виду в коде.
Если вам не нужно значение before-increment в вашем выражении, не используйте эту форму оператора. Это небольшая проблема, но если вы не работаете с руководством по стилю, которое полностью запрещает одну версию в пользу другой (так называемое руководство по стилю с костяными головами), вам следует использовать форму, которая наиболее точно отражает то, что вы пытаетесь сделать.
QED, используйте версию перед инкрементом:
источник
Разницу можно понять по следующему простому коду C ++:
источник
источник
я ++ и ++ я
Этот небольшой код может помочь визуализировать разницу под другим углом, чем уже опубликованные ответы:
Результат:
Обратите внимание на ситуации до и после.
для цикла
Что касается того, какой из них следует использовать в блоке приращения цикла for, я думаю, что лучшее, что мы можем сделать, чтобы принять решение, - это использовать хороший пример:
Результат:
Я не знаю о вас, но я не вижу никакой разницы в его использовании, по крайней мере, в цикле for.
источник
Следующий фрагмент кода C иллюстрирует различие между операторами увеличения и уменьшения до и после операции:
Операторы приращения:
источник
Предварительная обработка означает приращение на той же строке. Постинкремент означает приращение после выполнения строки.
Когда речь идет об операторах OR, AND, становится интереснее.
В массиве
В C ++ post / pre-инкремент переменной указателя
источник
Коротко:
++i
иi++
работает так же, если вы не пишете их в функции. Если вы используете что-то вродеfunction(i++)
илиfunction(++i)
вы можете увидеть разницу.function(++i)
говорит первое увеличение i на 1, после этого поместите этоi
в функцию с новым значением.function(i++)
говорит, поместите сначалаi
в функцию после этого увеличенияi
на 1.источник
int j = ++i;
иint k = i++;
даже тогда, когда нет вызова функции.Единственная разница - это порядок операций между приращением переменной и значением, которое возвращает оператор.
Этот код и его вывод объясняют разницу:
Выход:
Таким образом, в основном
++i
возвращает значение после его увеличения, в то время как++i
возвращает значение до его увеличения. В конце в обоих случаях значениеi
будет увеличено.Другой пример:
Вывод:
Много раз нет разницы
Различия очевидны , когда возвращаемое значение присваиваются другим переменным или , когда приращение выполняются в конкатенации с другими операциями , где применяются операция приоритет (
i++*2
отличается от++i*2
, но(i++)*2
и(++i)*2
возвращает то же значение) во многих случаях они являются взаимозаменяемыми. Классическим примером является синтаксис цикла for:имеет тот же эффект
Правило помнить
Чтобы не путать два оператора, я принял это правило:
Свяжите позицию оператора
++
относительно переменнойi
с порядком++
операции относительно назначенияСказал другими словами:
++
beforei
Приращение средств должно быть выполнено перед присваиванием;++
послеi
приращения средства должно быть выполнено после назначения:источник
Вы можете думать о внутреннем преобразовании этого как о множественных утверждениях ;
Вы можете думать это как,
Вы можете думать это как,
источник
a = i ++ означает, что содержит текущее значение i a = ++ i означает, что содержит увеличенное значение i
источник
a = i++;
означает, что значение, сохраненное в,a
будет значениемi
до приращения, но «без приращения» подразумевает, чтоi
это не приращение, что совершенно неправильно -i
увеличивается, но значение выражения является значением до приращения.Вот пример, чтобы понять разницу
вывод:
10 12/11 11
(в зависимости от порядка вычисления аргументовprintf
функции, который варьируется в зависимости от компиляторов и архитектур)Пояснение:
i++
->i
печатается, а затем увеличивается. (Печатает 10, ноi
становится 11)++i
->i
значение увеличивается и печатает значение. (Печатает 12, а значениеi
также 12)источник
i++
и++i