Инкремент, преинкремент и постинкремент - PullRequest
1 голос
/ 15 февраля 2012

Помогите мне решить эту проблему, пожалуйста.Далее следуют следующие выражения:

//Expression
offSpring1[m1++] = temp1;

// Шаги:

1.- увеличение m1

2.- назначение temp1 для offSpring

Я всегда думал, что выражение в скобках было первым, которое нужно было сделать.Но сейчас я в замешательстве.Так что, если a напишите это:

//Expression
offSpring1[++m1] = temp1;
//Steps would be:

1.- assign temp1 to offSpring
2.- increment m1

Если шаги будут такими же, как первые, в чем разница между i ++ и ++ i?

Ответы [ 10 ]

8 голосов
/ 15 февраля 2012
int i = 0;
std::cout << i++ << std::endl;
std::cout << i << "\nreset" << std::endl;
i = 0;
std::cout << ++i << std::endl;
std::cout << i << std::endl;

выход:

0
1
reset
1
1

i++ возвращает значение в текущем виде в выражении, затем увеличивает значение переменной. ++i увеличивает значение переменной, а затем возвращает значение для использования в текущем выражении.

3 голосов
/ 15 февраля 2012
offSpring1[m1++] = temp1;

есть

offSpring1[m1] = temp1;
m1 += 1;

и

offSpring1[++m1] = temp1;

это

m1 += 1;
offSpring1[m1] = temp1;
1 голос
/ 15 февраля 2012
  • j = ++i совпадает с i = i+1; j = i;
  • j = i++ совпадает с j = i; i = i+1;
1 голос
/ 15 февраля 2012

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

Для ++ i (предварительное приращение)

int main()
{
    int* offSpring = calloc(20,sizeof(int));
    int m1 =1;
    offSpring[++m1] = 10;
    printf("%d,%d",offSpring[m1],m1);
}

В первом вы получите 10 как значение offSpring [m1].Зачем?Потому что это оператор предварительного увеличения, который означает, что первый m1 увеличивается, а остальные оцениваются.

Для i ++ (после увеличения)

int main()
{
    int* offSpring = calloc(20,sizeof(int));
    int m1 =1;
    offSpring[m1++] = 10;
    printf("%d,%d",offSpring[m1],m1);
}

Во втором, потому что используется оператор постинкремента, вы получите значение 0, так как сначала вы присваиваете 10 для offSpring [m1], а затем m1 увеличивается.

0 голосов
/ 15 февраля 2012

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

Чтобы начать с разницы между a ++ и ++ a:

  • a ++ будет увеличивать a, но выражение, использующее его, будетпосмотрите значение a перед приращением
  • ++ a увеличит значение a, и выражение, использующее его, увидит увеличенное значение.
  • Элемент списка

с

buffer[a++] = b;

компилятор может решить сделать ++ в любой точке выражения.Таким образом, если 'b' на самом деле является выражением с участием a, вы можете получить разные результаты на разных компиляторах.Оба следующих условия будут действительны:

  • получить значение;
  • увеличить
  • , где буфер [старое значение] указывает на
  • оценивать b
  • хранить b

или

  • оценивать b;
  • работать там, где указывает буфер [a]в
  • хранилище b
  • с приращением a

, если бы 'b' включало a, эти 2 реализации дали бы разные результаты.Оба действительны.

0 голосов
/ 15 февраля 2012

У выражения (или подвыражения) есть два аспекта: его значение, и его побочные эффекты. Значение i ++ является значением i; значение ++ i - это значение i + 1, преобразованное в тип i. Это значение, используемое в выражении. Побочные эффекты обоих увеличить переменную i. Это может произойти в любое время после предыдущая точка последовательности и перед следующей. Предположим, i является глобальным переменная, и вы пишете что-то вроде:

i = 0;
f()[i ++] = g();
f()[++ i] = g();

Стандарт ничего не говорит о том, замечено ли значение i в f() или g() - это до увеличения или после. Ни в том, ни в другом случае. Все в стандарте говорится, что эффект от приращения происходит после начала полного выражения (но, возможно, как первым делом в полном выражении) и до конца. (И это они не будут чередоваться с вызовом функции, так что если f() читает i дважды, гарантированно будет видно одно и то же значение.)

0 голосов
/ 15 февраля 2012

Это работает точно так же, как вы описали:

offSpring1[m1++] = temp1 совпадает с offSpring[m1] = temp1; m1 = m1 + 1;

OffSpring1[++m1] = temp1 так же, как m1 = m1 + 1; OffSpring1[m1] = temp1;

Приращения нотации префикса перед вычислением выражения Приращения нотации префикса после вычисления выражения

0 голосов
/ 15 февраля 2012

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

offSpring1[m1++] = temp1;

Таким образом, даже если m1 увеличивается перед идексингом массива, значение temp1 присваивается в позиции m1 - 1.

0 голосов
/ 15 февраля 2012

Описание первого - это правильное описание второго.Правильное описание первого очень похоже, вам просто нужно добавить шаг «копировать текущее значение m1» перед остальными.

Но у вас здесь явно не хватает точек последовательности, если m1 имеетпримитивный тип.Правила несколько меняются между C ++ 03 и C ++ 11.

Если m1 имеет определенный пользователем тип, то задействуются вызовы функций, которые влияют на последовательность.


Этот код

offSpring1[m1++] = temp1;

выполняет следующее (если m1 является примитивным типом):

auto const old_m1(m1);
auto const new_m1(old_m1 + 1);
auto& lhs(offSpring[old_m1]);
parallel { lhs = temp1; m1 = new_m1; }

Этот код

offSpring1[++m1] = temp1;

точно такой жеза исключением того, что lhs связан с использованием new_m1 вместо old_m1.

. В любом случае не определено, записано ли lhs до или после m1.

Если m1 не является примитивным типом, он выглядит примерно так:

auto const& index = m1.operator++(0); // one argument
auto& lhs = offSpring.operator[](index);
lhs = temp1;

против

auto const& index = m1.operator++(); // no arguments
auto& lhs = offSpring.operator[](index);
lhs = temp1;

В обоих этих случаях изменение на m1 определенно выполняется допишите lhs.

0 голосов
/ 15 февраля 2012

offSpring1[m1++] = temp1; не делает то, что вы сказали.

  1. назначить temp_m1 = m1.
  2. приращение m1.
  3. индекс offSpring1[temp_m1]
  4. присваивает temp1 индексированное значение.

С другой стороны offSpring1[++m1] = temp1; работает так:

  1. приращение m1.
  2. индекс offSpring1[m1]
  3. присвоить temp1 индексированному значению.
...