Есть ли разница в производительности между i ++ и ++ i в C? - PullRequest
425 голосов
/ 24 августа 2008

Есть ли разница в производительности между i++ и ++i, если полученное значение не используется?

Ответы [ 13 ]

4 голосов
/ 04 июня 2014

Я могу вспомнить ситуацию, когда постфикс медленнее, чем приращение префикса:

Представьте себе, что процессор с регистром A используется в качестве аккумулятора, и это единственный регистр, используемый во многих инструкциях (некоторые маленькие микроконтроллеры действительно таковы).

Теперь представьте следующую программу и ее перевод в гипотетическую сборку:

Приращение префикса:

a = ++b + c;

; increment b
LD    A, [&b]
INC   A
ST    A, [&b]

; add with c
ADD   A, [&c]

; store in a
ST    A, [&a]

Постфиксный прирост:

a = b++ + c;

; load b
LD    A, [&b]

; add with c
ADD   A, [&c]

; store in a
ST    A, [&a]

; increment b
LD    A, [&b]
INC   A
ST    A, [&b]

Обратите внимание, как значение b было принудительно перезагружено. При увеличении префикса компилятор может просто увеличивать значение и продолжать использовать его, возможно, избегая его перезагрузки, поскольку желаемое значение уже находится в регистре после увеличения. Однако с постфиксным инкрементом компилятору приходится иметь дело с двумя значениями, одним старым и одним увеличенным значением, которое, как я покажу выше, приводит к еще одному доступу к памяти.

Конечно, если значение приращения не используется, например, один оператор i++;, компилятор может (и делает) просто генерировать инструкцию приращения независимо от использования постфикса или префикса.


В качестве примечания хочу отметить, что выражение, в котором есть b++, не может быть просто преобразовано в выражение с ++b без каких-либо дополнительных усилий (например, путем добавления - 1). Таким образом, сравнение двух, если они являются частью какого-либо выражения, не совсем корректно. Часто, когда вы используете b++ внутри выражения, вы не можете использовать ++b, поэтому даже если бы ++b были потенциально более эффективными, это было бы просто неправильно. Исключение, конечно, если выражение требует его (например, a = b++ + 1;, который можно изменить на a = ++b;).

2 голосов
/ 16 октября 2008

Я всегда предпочитаю предварительное увеличение, однако ...

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

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

Кроме того, если дать optmizer меньше, вероятно, компилятор будет работать быстрее.

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

Мой C немного ржавый, поэтому я прошу прощения заранее. По скорости я могу понять результаты. Но я не совсем понимаю, как оба файла оказались в одном хеше MD5. Может быть, цикл for выполняется так же, но не будут ли следующие 2 строки кода генерировать разные сборки?

myArray[i++] = "hello";

против

myArray[++i] = "hello";

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

Только мои два цента.

...