нужен ли язык preIncrement (++ x) и postIncrement (x ++) - PullRequest
3 голосов
/ 25 марта 2010

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

  • есть ли сценарий реального использования для этого
  • это не может быть сделано с помощью + =

    y = x++

    y = x
    x += 1

Ответы [ 3 ]

7 голосов
/ 25 марта 2010

Это просто более короткий способ написать то же самое, и это сбивает с толку тех, кто не понимает C (a) . Тот же аргумент может быть приведен для замены:

for (i = 0; i < 10; i++)
    printf ("%d\n", i);

с:

i = 0;
while (i < 10) {
    printf ("%d\n", i);
    i = i + 1;
}

, поскольку любое for также можно сделать с помощью while или:

i = 0;
loop: if (i < 10) {
    printf ("%d\n", i);
    i = i + 1;
    goto loop;
}

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


(a) Иногда мне нравится объяснять это моим студентам в виде простых утверждений и побочных эффектов, что позволяет коду C быть более лаконичным, обычно с минимальной потерей читаемости или минимальными потерями.

Для утверждения:

y = x++;

оператор присваивает x y с побочным эффектом, который впоследствии увеличивает x. ++x то же самое, просто побочный эффект происходит заранее.

Точно так же побочным эффектом присвоения является то, что оно оценивается как присвоенное значение, что означает, что вы можете делать такие вещи как:

while ((c = getchar()) != -1) count++;

и что делает такие вещи как:

42;

совершенно правильные, но бесполезные операторы Си.

6 голосов
/ 25 марта 2010

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

В те времена, когда C был в основном высокоуровневым ассемблером для машин PDP-11 </flamebait>, и задолго до того, как у нас были хорошие оптимизирующие компиляторы, которые у нас сейчас есть, были распространенные идиомы, что операторы постинкрементного вычисления идеально для. Вещи как это:

char* strcpy(char* src, char* dest)
{
  /* highly simplified version and likely not compileable as-is */
  while (*dest++ = *src++);
  return dest;
}

Код, о котором идет речь, генерировал код машинного языка PDP-11 (или другой), который интенсивно использовал базовые режимы адресации (например, относительный прямой и относительный косвенный), который включал именно эти виды операций до и после увеличения и уменьшения .

Итак, чтобы ответить на ваш вопрос: нужны ли эти языки сегодня? Нет, конечно нет. Можно доказать, что вам нужно очень мало с точки зрения инструкций для вычисления вещей. Вопрос более интересен, если вы спросите: «Эти функции желательны?» На это я бы ответил квалифицированным «да».

Используя ваши примеры:

y = x;
x += 1;

против

y = x++;

Я вижу два преимущества прямо на макушке головы.

  1. Код более лаконичен. Все, что мне нужно знать, чтобы понять, что вы делаете, находится в одном месте (если, конечно, я знаю язык!) Вместо того, чтобы распространяться. «Распределение» по двум строкам кажется придирчивым, но если вы делаете тысячи из них, это может иметь большое значение.
  2. Гораздо более вероятно, что код, сгенерированный даже дерьмовым компилятором, будет атомарным во втором случае. В первом случае, скорее всего, не будет, если у вас нет хорошего компилятора. (Не все платформы имеют хорошие, сильные оптимизирующие компиляторы.)

Кроме того, я нахожу очень убедительным, что вы говорите о +=, когда это само по себе является "ненужным" способом сказать x = x + 1; .... В конце концов, я не могу придумать сценарий использования +=, который не может быть подан в порядке _ = _ + _.

0 голосов
/ 06 декабря 2014

Вы случайно подняли здесь гораздо большую проблему, и она будет становиться все более известной вам с годами (десятилетиями).

Языки часто совершают ошибку, предоставляя «способности», когда они не должны этого делать. IMO, ++ должен быть отдельным оператором только , и абсолютно не оператором выражения.

Старайтесь держать близко к сердцу следующее: Цель состоит не в том, чтобы создать код для чтения компетентным инженером. Цель состоит в том, чтобы создать код для компетентного инженера, который он будет читать, когда в 3 часа ночи он измотан и запит кофеином. Если инженер говорит вам: «Все конструкции кода могут доставить вам неприятности. Вам просто нужно знать, что вы делаете», - и уходите, смеясь, потому что он просто разоблачил себя как часть проблемы.

Другими словами, никогда не кодируйте ничего подобного:

a[aIndex++] = b[++bIndex];

Вы можете найти интересную беседу о таких вещах здесь: Почему в JavaScript избегают операторов увеличения ("++") и уменьшения ("-")?

...