Ответ 1
Примечание: вы вызываете поведение undefined (дважды изменяя переменную между точками последовательности)
Возможные дубликаты:
Что эффективнее я ++ или ++ i?
Как объяснить результат выражения (++ x) + (++ x) + (++ x)?
Разница между я ++ и ++ я в цикле?
Привет, я пытаюсь использовать эти две программы
void fun(){
int k=0;
int i=10;
k = (i++)+(++i);
cout<<k<<endl;
}
Output = 22 as i++ will give 10 and ++i will evaluate into 12
но
void fun(){
int k=0;
int i=10;
k = (++i)+(++i);
cout<<k<<endl;
}
Output = 24
Это должно быть 23, я думаю, или есть sth, что я не могу видеть
Заранее спасибо
Примечание: вы вызываете поведение undefined (дважды изменяя переменную между точками последовательности)
В соответствии с С++ 03 Standard 5/4 поведение рассматриваемых программ undefined:
За исключением тех случаев, когда отмечено, порядок оценки операндов отдельных операторов и подвыражений инди- визуальные выражения и порядок, в которых происходят побочные эффекты, не определены. 53) Между предыдущими и следующая точка последовательности скалярный объект должен иметь свое сохраненное значение, измененное не более чем один раз оценкой выражения. Кроме того, к предыдущему значению следует обращаться только для определения значения, которое необходимо сохранить. Требования настоящего параграфа выполняются для каждого допустимого упорядочения подвыражений полного выражение; в противном случае поведение undefined.
Это казалось действительно интересным, поэтому я заглянул в разборку (MSVС++ 2008)
k = (++i)+(++i);
0122413C mov eax,dword ptr [i]
0122413F add eax,1
01224142 mov dword ptr [i],eax
01224145 mov ecx,dword ptr [i]
01224148 add ecx,1
0122414B mov dword ptr [i],ecx
0122414E mov edx,dword ptr [i]
01224151 add edx,dword ptr [i]
01224154 mov dword ptr [k],edx
Как вы можете видеть, он дважды увеличивает i
, а затем добавляет i
к себе. То же самое происходит, если есть несколько экземпляров (++i)
.
В любом случае, поскольку стандарт ничего не гарантирует, изменение i
более одного раза приведет к поведению undefined.
Переменная никогда не должна увеличиваться более одного раза в одном из операторов, потому что поведение компилятора не определено.
Чтобы избежать побочных эффектов, сделайте два утверждения для своих примеров.
Пример 1: k = я ++; k + = ++ i;
Пример 2: k = ++ i; k + = ++ i;
Если вы это сделаете, ваш код будет работать правильно.
Я предполагаю, что оба оператора pre-increment работают до того, как вычисляется оператор добавления. следовательно, 24.
Все зависит от того, как компилятор видит, что вы делаете, но я предполагаю, что вы видите.
i ++ - это пост-инкремент, ++ я - pre-increment. я ++ будет увеличивать я после завершения инструкции.
Чтобы проиллюстрировать в ваших примерах:
Пример 1:
k = 0
i = 10
i += 1
k = i + i // 11 + 11
i += 1
Пример 2:
k = 0
i = 10
i += 1
i += 1
k = i + i // 12 + 12
++ я даст результат я = я + 1. Если я = 10, то в k = (++ i) + (++ i); выражение (++ i) даст добавочное значение, означающее, что произойдет первое приращение, но в случае я ++ приращение будет влиять на я после выражения.
So я = 10
k = (i ++) + (++ i);
10 11 12
10 + 12=22
k = (++ i) + (++ i);
11 11 12
11 + 12=23
++i
обычно возвращает ссылку на самую переменную, поэтому вторая модификация также влияет на память, которая содержит результат от первой модификации. (Post-increment i++
, с другой стороны, должен возвращать копию значения для правильной работы.)
Типичное определение ++i
в С++ (с использованием перегрузки оператора) было бы
struct Foo{
//...
Foo const & operator++(){ //this implements ++i
//do something to increment
return *this;
}
Foo operator++(int){ //this implements i++
Foo old(*this);
//do something to increment
return old;
}
};
++ я происходит до вычисления всего выражения, а я ++ - после. В первом примере один из приращений происходит до вычисления значения, поэтому "i" становится равным 21, и вы получаете 21 + 21. В последнем примере оба случаются раньше, поэтому "i" становится 22, и вы получаете 22 + 22.
Чтобы определить это, выполните следующий шаг.
1). Определяется все ++i
.
2). Значение я затем используется для каждого термина, который равен ++i
и i++
.
3). Определяется все i++
.
Первый случай:
int k=0;
int i=10;
k = (i++)+(++i);
1) Существует один из ++i
, поэтому на конце этого шага я = 11 (один раз).
2) Теперь он становится k = (11)+(11);
3) Существует один из i++
, поэтому на конце этого шага я = 12 (один раз).
Второй случай:
int k=0;
int i=10;
k = (++i)+(++i);
1) Существует один из ++i
, поэтому на конце этого шага я = 12 (дважды).
2) Теперь он становится k = (12)+(12);
3) Существует один из i++
, поэтому на конце этого шага я = 12 (нулевое время).
Создаю тестовый код:
#include <stdio.h>
int main(void) {
int K=0;
int I=10;
K = (I++)+(++I);
printf("I: %d; K: %d\n", I, K);
K=0;
I=10;
K = (++I)+(++I);
printf("I: %d; K: %d\n", I, K);
}
При выполнении результат:
I: 12; K: 22
I: 12; K: 24
Надеюсь, что это поможет.