2016-09-23 6 views
7

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

Я могу видеть аргументы для конкретного оператора приращения; у многих процессоров в то время был особый код операции инкремента, который был быстрее, чем добавление, и концептуально «приращение» представляет собой отличную идею от «add», теоретически имея в виду, что они могут быть написаны по-разному, может сделать код более читаемым.

То, что я не понимаю, является необходимостью для оператора предварительного инкремента. Не может ли это быть написано так?

#This... 
x = i++; 
#becomes this: 
x = i; 
++i; 

Есть ли историческая причина, о которой я не знаю, может быть? Вы не смогли «выбросить» возвращаемые значения операторов в изначальных версиях C?

+0

Можно ли отредактировать этот вопрос, чтобы довести его до масштабов? Я с удовольствием отредактирую свой ответ и добавлю какой-то исторический контекст, но я не буду больше заниматься этим, пока вопрос не будет снят. Мне также нужно знать, какие операторы приращения решаются (извините за каламбур). – Mick

+0

[Этот вопрос обсуждается по мета] (http://meta.stackoverflow.com/questions/335085/is-it-okay-to-delete-and-re-make-a-question-to-stop-everyone -hyperfocusing-on-a) и после удаления здесь было [повторно запрошено в уточненной форме на Programmers] (http://programmers.stackexchange.com/questions/331870/origins-of-having-both-prefix- incrementi-и-постфикс-incrementi-в). Для прозрачности, пока эти обсуждения продолжаются, я восстановил ее здесь и наложил временную (1-дневную) блокировку. – Shog9

ответ

12

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

register char *ptr1; 
register char *ptr2; 
... 
for (...) { 
    *ptr1++ = *ptr2++; /* post-increment */ 
} 

компилятор, который я когда-то работал с (на собственном миникомпьютере) будут генерировать следующие операции регистра для выполнения задания:

load $r1,*$a1++  // load $r1 from address in $a1 and increment $a1 
store $r1,*$a2++  // store $r1 at address in $a2 and increment $a2 

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

Я считаю, что мини-ЭВМ DEC, на которых первоначально был разработан C, имели такие режимы адресации. Машина, над которой я работал, не была сделана DEC, но архитектура была очень похожа.

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

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

-2

Таким образом, вы можете, например, сделать это

While (++i < threshold) [do something]; 

и это ...

While (i++ < threshold) [do something]; 

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

+0

Это кажется ужасно конкретным, хотя. Вы уверены, что это фактическая историческая причина? – Schilcote

+0

Нет исторической причины - у них разные цели. – NonCreature0714

+0

Это действительно интересные варианты. с ++ i <порогом. После того, как цикл будет выполнен, значение будет за пределами последнего обработанного индекса, т.е. С i ++ это два. ++ i лучше для цикла while, так как max действительный индекс +1 обрабатывается с помощью i ++. Посмотрите на все итерации (i ++ <2) по сравнению с (++ i <2), чтобы увидеть различие. Но, [++ i] = b [i] - запутанная конструкция ... – BenPen

Смежные вопросы