Почему делает n ++, выполняются быстрее, чем n=n+1?

На языке C, Почему делает n++ выполнитесь быстрее, чем n=n+1?

(int n=...;  n++;)
(int n=...;  n=n+1;)

Наш преподаватель задал тот вопрос в сегодняшнем классе. (это не домашняя работа),

31
задан 13 revs, 8 users 28% 10 June 2010 в 21:20
поделиться

8 ответов

Это будет верно, если вы работаете над компилятор "каменного века" ...

В случае "каменный век" :
++ n быстрее, чем n ++ быстрее, чем n = n + 1
Машина обычно имеет приращение x , а также add const к x

  • В случае n ++ вы будете иметь только 2 доступа к памяти (чтение n, inc n, запись n)
  • В случае n = n + 1 у вас будет 3 доступа к памяти (чтение n, чтение const, добавление n и const , напишите n)

Но сегодняшний компилятор автоматически преобразует n = n + 1 в ++ n , и он сделает больше, чем вы можете себе представить !!

Также на сегодняшних вышедших из строя процессорах - несмотря на случай "каменного века" компилятора - во многих случаях время выполнения не может быть затронуто вообще !!

Связанные

102
ответ дан 27 November 2019 в 21:19
поделиться

Компилятор превратит n + 1 в ничто.

Вы имеете в виду n = n + 1 ?

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

14
ответ дан 27 November 2019 в 21:19
поделиться

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

2
ответ дан 27 November 2019 в 21:19
поделиться

Фактически, причина в том, что оператор определяется иначе для пост-исправления, чем для предварительного исправления. ++ n увеличит «n» и вернет ссылку на «n», в то время как n ++ увеличит «n», вернет копию const числа «n» . Следовательно, фраза n = n + 1 будет более эффективной. Но я должен согласиться с приведенными выше плакатами. Хорошие компиляторы должны оптимизировать неиспользуемый возвращаемый объект.

2
ответ дан 27 November 2019 в 21:19
поделиться

В языке Си побочный эффект выражения n++ по определению эквивалентен побочному эффекту выражения n = n + 1. Поскольку ваш код полагается только на побочные эффекты, сразу становится очевидным, что правильный ответ состоит в том, что эти выражения всегда имеют абсолютно эквивалентную производительность. (Независимо от любых настроек оптимизации в компиляторе, BTW, поскольку этот вопрос не имеет абсолютно никакого отношения ни к каким оптимизациям.)

Любое практическое расхождение в производительности этих выражений возможно только если компилятор намеренно (и злонамеренно!) пытается ввести это расхождение. Но в данном случае оно, конечно, может пойти в любую сторону, т.е. в ту, в какую захочет автор компилятора.

2
ответ дан 27 November 2019 в 21:19
поделиться

Современные компиляторы должны уметь распознавать обе формы как эквивалентные и преобразовывать их в формат, который лучше всего работает на вашей целевой платформе. Есть одно исключение из этого правила: доступ к переменным, имеющий побочные эффекты. Например, если n - это некоторый отображенный в память аппаратный регистр, чтение из него и запись в него могут делать больше, чем просто перенос значения данных (например, чтение может очистить прерывание). Вы могли бы использовать ключевое слово volatile , чтобы сообщить компилятору, что ему нужно быть осторожным при оптимизации доступа к n , и в этом случае компилятор может сгенерировать код, отличный от n ++ (операция увеличения) и n = n + 1 (операции чтения, добавления и сохранения). Однако для обычных переменных компилятор должен оптимизировать обе формы для одного и того же.

3
ответ дан 27 November 2019 в 21:19
поделиться

Кто сказал, что он есть? На самом деле ваш компилятор оптимизирует все это, что делает его спорным.

5
ответ дан 27 November 2019 в 21:19
поделиться

На GCC 4.4.3 для x86, с или без оптимизаций, они компилируются в совершенно одинаковый ассемблерный код, и поэтому занимают одинаковое количество времени на выполнение. Как вы можете видеть в ассемблере, GCC просто преобразует n++ в n=n+1, а затем оптимизирует его в одноинструкционное сложение (в -O2).

Предположение вашего преподавателя, что n++ быстрее, применимо только к очень старым, неоптимизирующим компиляторам, которые не были достаточно умны, чтобы выбрать инструкции обновления на месте для n = n + 1. Такие компиляторы уже давно устарели в мире ПК, но их все еще можно найти для странных проприетарных встроенных платформ.

Си код:

int n;

void nplusplus() {
    n++;
}

void nplusone() {
    n = n + 1;
}

Выходной ассемблер (без оптимизаций):

    .file   "test.c"
    .comm   n,4,4
    .text
.globl nplusplus
    .type   nplusplus, @function
nplusplus:
    pushl   %ebp
    movl    %esp, %ebp
    movl    n, %eax
    addl    $1, %eax
    movl    %eax, n
    popl    %ebp
    ret
    .size   nplusplus, .-nplusplus
.globl nplusone
    .type   nplusone, @function
nplusone:
    pushl   %ebp
    movl    %esp, %ebp
    movl    n, %eax
    addl    $1, %eax
    movl    %eax, n
    popl    %ebp
    ret
    .size   nplusone, .-nplusone
    .ident  "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
    .section    .note.GNU-stack,"",@progbits

Выходной ассемблер (с оптимизациями -O2):

    .file   "test.c"
    .text
    .p2align 4,,15
.globl nplusplus
    .type   nplusplus, @function
nplusplus:
    pushl   %ebp
    movl    %esp, %ebp
    addl    $1, n
    popl    %ebp
    ret
    .size   nplusplus, .-nplusplus
    .p2align 4,,15
.globl nplusone
    .type   nplusone, @function
nplusone:
    pushl   %ebp
    movl    %esp, %ebp
    addl    $1, n
    popl    %ebp
    ret
    .size   nplusone, .-nplusone
    .comm   n,4,4
    .ident  "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
    .section    .note.GNU-stack,"",@progbits
42
ответ дан 27 November 2019 в 21:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: