Страницы

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

Показаны сообщения с ярлыком инкремент. Показать все сообщения
Показаны сообщения с ярлыком инкремент. Показать все сообщения

воскресенье, 15 марта 2020 г.

Почему нельзя 2 + + ++3?

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


В этом ответе разобрались, что 2 + + 3 читается компилятором как 2 + (+3), то есть
второй плюс — унарный.

В таком случае, почему не работает такое?

2 + + ++3


Как бы я это понимал, будучи компилятором:

2 + ( +( ++3 ) )



( ++3 ) — выполнить инкремент и вернуть значение 4
( +4 ) — унарный плюс к 4, вернуть 4.
2 + 4, сложение, вернуть 6.


Где ошибка в моем внутреннем компиляторе Java?

Кстати, 2 + + 3++ тоже не работает.
    


Ответы

Ответ 1



Сам понял! Потому что инкременты нельзя применять к константам. Такое работает: int a = 2; int b = 3; System.out.println(+ a++ + + ++b);

среда, 29 января 2020 г.

Постинкремент при возвращении значения функции

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


Почему функция

int f(int k) { return k++; } 


возвращает значение k вместо k+1, даже если записать ее в виде: 

int f(int k) { return (k++); }


?
    


Ответы

Ответ 1



Именно потому что это постинкремент. Результат постинкремента - это значение до изменения. Наличие дополнительных скобок не меняет значения выражения. Если бы Вы записали: k++; return k; то вернулось бы уже инкрементированное значение, т.к. после ; переменная уже изменится. Понимание эффекта возможно упростит использование функции вместо постинкремента вида: int inc(int i) { int t = i; i = i + 1; return t; }

Ответ 2



Потому что постфиксный инкремент дает в качестве значения выражения значение переменной до инкремента. Вот и все. Хотите возвращать k+1 - пишите return ++k;...

Ответ 3



В этом заключается смысл различия между пре-инкрементным оператором и пост-инкрементным оператором. Пост-инкрементный оператор возвращает значение переменной до ее инкремента. Из стандарта c++ (5.2.6 Increment and decrement) 1 The value of a postfix ++ expression is the value of its operand. [Note: the value obtained is a copy of the original value —end note] Если бы переменная k была бы объявлена как глобальная переменная int k; int f(){ return k++; } то, действительно, после выхода из функции ее значение увеличилось бы на 1. Хотя тем не менее сама функция вернула бы исходное значение переменной. Рассмотрите следующую демонстрационную программу #include int k = 0; int f(){ return k++; } int g( int k ){ return k++; } int main() { std ::cout << "f() = " << f() << std::endl; std ::cout << "k = " << k << std::endl; std::cout << std::endl; k = 0; std ::cout << "g( k ) = " << g( k ) << std::endl; std ::cout << "k = " << k << std::endl; return 0; } Вывод программы на консоль f() = 0 k = 1 g( k ) = 0 k = 0 Обе функции вернули одно и то же значение 0. После вызова первой функции k увеличилась на 1, так как функция имеет дело непосредственно с глобальной переменной. Во втором случае переменная k не изменилась, так как вторая функция имеет дело с копией значения переменной. Ее параметр - это локальная переменная функции.

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

Почему две одинаковые математические операции в двух языках возвращают разное значение?

#c_sharp #cpp #инкремент


C#:    

int a = 3;
Console.WriteLine(++a * --a);




12


C++:

int a = 3;
std::cout << ++a * --a << std::endl;




9

    


Ответы

Ответ 1



Ничего "одинакового" в этих "операциях" нет. Это не говоря уже о том, что не стоит назвать операции с побочными эффектами "математическими". Язык C# (или, например, Java) однозначно определяет семантику выражения ++a * --a. В языке С++ поведение выражения ++a * --a не определено, ибо такое выражение содержит две неупорядоченных (unsequenced) относительно друг друга модификации одной и той же переменной a. То есть в языке С++ у этого выражения нет никакого конкретного результата или поведения. Как правильно заметил @VTT в комментариях, одним из допустимых проявлений неопределенного поведения является отказ компилятора компилировать такой код.

суббота, 14 декабря 2019 г.

Почему данный код выводит число 13?

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


Объясните пожалуйста, почему данный код выводит число 13? 

var i = 5;
i = ++i + ++i;
console.log(i); // 13

    


Ответы

Ответ 1



++i - это преинкремент. Он вычисляется перед использованием переменной. Т.е, вычислилось первое ++i, в i теперь 6, выражение теперь 6 + (++6). Потом вычислили второе ++i, в i теперь 7. Потом сложили 6 + 7, получили 13. С другой стороны, к примеру, если взять постинкремент i++. После i = i++ + i++; в i будет 11, т.к. постинкремент вычисляется после использования переменной. Т.е, подставилось в выражение, вычислилось первое i++, в i теперь 6, получили выражение 5 + (6++). Потом второе i++, в i было 6, оно и подставилось, стало 5 + 6, после чего i стало равно 7. Cложили 5 + 6, получили 11.

Ответ 2



Все верно. Сначала выполняется "первый" i++, потом "второй". Лишь потом складывается.

воскресенье, 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! ответов в английском стэковерфлоу.

среда, 5 июня 2019 г.

Почему нельзя 2 + + ++3?

В этом ответе разобрались, что 2 + + 3 читается компилятором как 2 + (+3), то есть второй плюс — унарный.
В таком случае, почему не работает такое?
2 + + ++3
Как бы я это понимал, будучи компилятором:
2 + ( +( ++3 ) )
( ++3 ) — выполнить инкремент и вернуть значение 4 ( +4 ) — унарный плюс к 4, вернуть 4 2 + 4, сложение, вернуть 6
Где ошибка в моем внутреннем компиляторе Java?
Кстати, 2 + + 3++ тоже не работает.


Ответ

Сам понял! Потому что инкременты нельзя применять к константам. Такое работает:
int a = 2; int b = 3; System.out.println(+ a++ + + ++b);

пятница, 9 ноября 2018 г.

Почему данный код выводит число 13?

Объясните пожалуйста, почему данный код выводит число 13?
var i = 5; i = ++i + ++i; console.log(i); // 13


Ответ

++i - это преинкремент. Он вычисляется перед использованием переменной.
Т.е, вычислилось первое ++i, в i теперь 6, выражение теперь 6 + (++6). Потом вычислили второе ++i, в i теперь 7. Потом сложили 6 + 7, получили 13
С другой стороны, к примеру, если взять постинкремент i++
После i = i++ + i++; в i будет 11, т.к. постинкремент вычисляется после использования переменной.
Т.е, подставилось в выражение, вычислилось первое i++, в i теперь 6, получили выражение 5 + (6++). Потом второе i++, в i было 6, оно и подставилось, стало 5 + 6, после чего i стало равно 7. Cложили 5 + 6, получили 11