Страницы

Поиск по вопросам

воскресенье, 8 декабря 2019 г.

Как работает выражение i = i++? [дубликат]

#java #инкремент


        
             
                
                    
                        
                            This question already has answers here:
                            
                        
                    
                
                        
                            Почему x = x++ не приводит к увеличению значения x в цикле?
                                
                                    (4 ответа)
                                
                        
                                Closed 1 год назад.
            
                    
Есть код:

 int i = 1;
 i=i++;
 System.out.println(i);


ВНЕЗАПНО 

Output:1

Вопрос: Почему выдаёт единицу? Я считаю, что должна дать двойку. Ну и что что постфиксная
запись? Даже если оно сначала бы присвоила i единицу, то потом всё равно должно было
увеличить значение i на единицу. 

PS. Мне хочется получить ответ по шагам, типа:


Сначала оно делает это, потому что... 
Потом оно делает это, потому что...

    


Ответы

Ответ 1



Возможно понятнее будет на уровне байткода. Ваш код будет скомпилирован в 0: iconst_1 // Загрузить константу 1 в стек 1: istore_1 // Сохранить значение из стека в локальную переменную i 2: iload_1 // Загрузить значение локальной переменной i в стек (в стеке 1) 3: iinc 1, 1 // Увеличить значение локальной переменной i на 1 (в переменной теперь 2) 6: istore_1 // СОХРАНИТЬ ЗНАЧЕНИЕ ИЗ СТЕКА В ПЕРЕМЕННУЮ i (в переменной опять 1) 7: getstatic #2 10: iload_1 // Загрузить в стек значение переменной i 11: invokevirtual #3 // Вывести значение Я не нашёл конкретного описания этого поведения в Java Language Specification, но оно не противоречит разделам 15.14.2 и 15.26.1 описывающим порядок разбора выражений постинкремента и присваивания.

Ответ 2



int i = 1; // вместо i = i++; int __temp = i; i = i + 1; i = __temp; System.out.println(i); Что происходит в строке i = i++; Сначала вычисляется правая часть. Запоминается значение i (равное 1). Потом значение i увеличивается на один. Потом возвращается запомненное значение 1. Потом выполняется присваивание значения 1 переменной i. Это то же самое, что написано в других ответах.

Ответ 3



В вашем примере используется post-increment (i++), в этом случае вы сначала получите старое значение, а уже затем добавите один к текущему значению(++). Чтобы получить 2 необходимо использовать pre-increment: ++i (прошу заметить инкремент перед именем переменной).

Ответ 4



Вот смотрите, такой код: int i = 1; i = i++; int a = i; System.out.println(a + "" + i); int b = i++; System.out.println(b + "" + i); выводит 11 // обратите внимание, что i снова вернулось значение 1 12 // i уже равно 2, но b получает старое значение i то есть, выражение N=i++ действительно увеличивает i на единицу, но переменной N будет присвоено значение, которое было у i до увеличения - по такому закону работает постфикс. "Изюминка" в вашем вопросе состоит в том, что переменную i вы действительно увеличили на единицу, но потом "внезапно" той же переменной i присвоили значение, которое было до увеличения - и переменная i у вас снова стала равна 1. Ответ "по шагам": причина такого результата в следующем - сначала делается операция увеличения i на единицу, а потом делается операция присвоения левой переменной значения i, которое было вначале. Если и слева и справа одна и та же переменная, то вторая операция естественно "затирает" все предыдущие операции.

Ответ 5



int i = 1; // i=1 i++ // i=2, значение выражения 1 i = ...; // присвоить 1 в переменную i - получается i=1

Ответ 6



Дружище для начала надо понять как работает оператор ++ есть int i = 1; OperatorPlusPlus(i); int OperatorPlusPlus(int yourNumber){ int tmp = yourNumber; int yourNumber = yourNumber + 1; return tmp; } То есть вы получаете значение переменной tmp и i у вас равна 2, далее вы i (2) присваивание значение tmp(1)

Ответ 7



Начнём с азов работы инкремента. Возьмём пример: int x = 1; int y = x++; System.out.println(y +""+x); Output:12 В первом приближении может казаться, что во второй строчке произошло следующее: Сначала произошло присвоение текущего значения, в переменную y записали единицу. Потом переменная x увеличилась на единицу. Однако более пристальный взгляд, говорит что всё оказалось гораздо сложнее. Для этого нужно глянуть декомпилированный байт-код этого же примера: byte x = 1; //int x = 1 - ориг. код byte var10000 = x; //2 строка ориг. кода int x1 = x + 1; //2 строка ориг. кода byte y = var10000; //2 строка ориг. кода System.out.println(y + "" + x1); Из него, можно вполне видеть, что эквивалентом "простой" строчки int y = x++;становятся сразу три строки. Похоже они работают следующим образом: Сначала выделяется переменная var10000 в которую записывается x; После происходит создание переменной x1 в которой происходит увеличение значения на единицу. Далее переменной y присваивается значение var10000 - то есть старого значения x. Получается, что префиксный инкремент содержит в себе создание двух новых переменных. Из вышесказанного очевидно, что исходное выражение: int i = 1; i=i++; System.out.println(i); в декомпилированном байт коде будет выглядеть, как: byte i = 1; //x заменили на i byte var10000 = i; int i1 = i + 1; i = var10000; //Мы по сути y заменили i System.out.println(i); То есть, последняя операция перед выводом на консоль - это запись в переменную i временного значения. В соответствии с приоритетом операций, присваивание всегда выполняется после инкремента\декремента. PS. Дополнительно, на аналогичный вопрос дали 17! ответов в английском стэковерфлоу.

Комментариев нет:

Отправить комментарий