Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > .NET для новичков > int i = 0; i += i++;


Автор: Kuvaldis 2.10.2007, 16:08
Вот сходил я, С++-ник, на собеседование по .NET
И задали мне вопрос:
Код

 int i = 0;
 i += i++;    
// i = ?

C точки зрения С++ получается 1, что я и скачал, но правильный ответ - 0
Я не совсем понимаю, почему.
Был бы рад услышать объяснение

СУВ, Kuvaldis

Автор: ivashkanet 2.10.2007, 16:20
Kuvaldis, ИМХО: сразу посылаешь их наф с таким вопросом и говоришь, что как захотели разработчики компилятора, так и будет!

Как получить ноль?.. Могу предположить, что в i += i++:

1) Берется сначала значение i (ноль) 
2) Происходит инкремент (i=1)
3) Выполняется операция увеличения i (шарп собака, сохраняет старое значение i и берет его) на значение справа (ноль из первой строки).

В общем еще один пример UB 

Удачи ;-)

Автор: ivashkanet 2.10.2007, 17:01
Еще момент:
эта строчка ведь эквивалентна строчке:
Код
i = i + i++;

В результате которой никто не сомневается....

Автор: tol05 2.10.2007, 17:35
Цитата(ivashkanet @  2.10.2007,  16:20 Найти цитируемый пост)
1) Берется сначала значение i (ноль) 
2) Происходит инкремент (i=1)
3) Выполняется операция увеличения i (шарп собака, сохраняет старое значение i и берет его) на значение справа (ноль из первой строки).

немного не так.
- берется значение ноль (i) и к нему прибавляется ноль (временное значение, прочитанное из i). Результат сохранается в i (ноль)
- инкрементируется временное значение, прочитанное из i (получается единица).

т.е.
Код

int i = 0;     //i=0
i += i++;      //i=i + tempInt, где  tempInt=0
               //tempInt = 1
// i = ?       //i=0

Код

i = i + i++;

i=0 smile можно в дебаггере посмотреть

Автор: ivashkanet 2.10.2007, 17:48
Цитата(tol05 @  2.10.2007,  17:35 Найти цитируемый пост)
немного не так.

Пусть будет так ;-) (у меня есть вопросы и к твоему и к моему объяснению smile )
Цитата(tol05 @  2.10.2007,  17:35 Найти цитируемый пост)
можно в дебаггере посмотреть 

Это выражение можно и без дебагера подсчитать (о чем я и говорил)

Автор: Kuvaldis 2.10.2007, 18:42
tol05, 
Цитата

 временное значение, прочитанное из i

А откуда здесь временная переменная?
Я пытаюсь разницу с С++ понять в данном вопросе. 

Автор: NikeDeForest 2.10.2007, 19:01
[offtopic]
А там из спичек ничего не просили собрать? 
Чем они обоснуют такой вопрос? Тем, что такое можно встретить в коде их разработчиков? Тогда беги от туда, таким го*но месить, а не код писать. smile
[/offtopic]

Автор: tol05 2.10.2007, 21:46
Цитата(Kuvaldis @  2.10.2007,  18:42 Найти цитируемый пост)
А откуда здесь временная переменная?
Я пытаюсь разницу с С++ понять в данном вопросе.  

выражение 
Код

i += i++; 

для меня означает: 
1. возьми i
2. увеличь его на значение, равное i 
3. присвой результат тому же i
4. после увеличения, инкрементируй "значение, равное i" (но не i)

здесь смешались понятия постфиксной формы инкремента и операндов операций (все-таки то, что стоит слева от знака "=" - не то же самое, что стоит справа smile ).

Непонятно? 
Цитата(ivashkanet @  2.10.2007,  17:48 Найти цитируемый пост)
(у меня есть вопросы и к твоему и к моему объяснению smile )
у меня тоже  smile 
Проще всего разобраться как будут выглядеть операции в ассемблере.
В ячейку, содержащую i, записывается результат сложения двух регистров. В регистр А записывается значение из ячейки i, в регистр В - такое же значение. Происходит сложение значений двух регистров, результат записывается в ячейку i и только потом значение регистра В инкрементируется. 

если бы было написано так:
Код

i += i;
i++;

тогда да, было бы увеличение i через правый операнд (который в данный момент равен i, но им не является). А потом - инкремент i. Потому что компилятор расшифровывает одинокое выражение i++ как i=i+1.

Kuvaldis, я думаю, тебе стоит почитать стандарт http://www.ecma-international.org/publications/standards/Ecma-334.htm, раздел 14.5.9 (postfix) и 14.6.5 (prefix)
Там написано, что могут хотеть 
Цитата(ivashkanet @  2.10.2007,  16:20 Найти цитируемый пост)
разработчики компилятора
, а чего - нет  smile 

NikeDeForest, это прекрасный вопрос, для проверки глубины понимания синтаксических конструкций. Я как-то на похожем вопросе засыпался. 
Цитата(NikeDeForest @  2.10.2007,  19:01 Найти цитируемый пост)
Тем, что такое можно встретить в коде их разработчиков? 
Тем более, ИМХО, бежать нужно не "оттуда", а "туда". Нужно считать расход памяти на операции потому что... 
В моем коде такое тоже можно встретить, и чем больше проходит времени, тем все чаще и чаще smile

Автор: NikeDeForest 3.10.2007, 05:52
Цитата

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

Код не должен содержать в себе такие конструкции, код должен быть легко и удобочитаемым.

Цитата

Тем более, ИМХО, бежать нужно не "оттуда", а "туда". Нужно считать расход памяти на операции потому что... 
В моем коде такое тоже можно встретить, и чем больше проходит времени, тем все чаще и чаще smile

Это микрооптимизация, которая должна быть обоснованна и документирована. При этом оптимизацию не проводят на первоначальном этапе конструирования, она проводится не на протяжении всего кода, а на критическом участке.
А что по поводу того, что у тебя это почти везде подряд попадается, то без обид конечно, но имхо, это пижонство, которое не оценит тот, кто будет читать твой код.
К тому же оптимизация на .НЕТ - это штука ненадежная. Хочу привести пример, но пора уже бежать. Через пару часов попробую, если не забуду.


Автор: Alek86 3.10.2007, 07:29
эээ ну в С++ стандарте насчет подобных примеров было ясно сказано, что будет неопределенность
и все на форумах давно обматерили тех, кто на собеседовании задает подобные вопросы.

есть у кого ссылка на шарповский "стандарт", где эта ситуация обговорена?

ато и здесь может стать анекдотичный вопрос. чему будет равно i:

Код

 i = 5;
 i = i++ + ++i;

Автор: Kuvaldis 3.10.2007, 08:51
Alek86, 
Цитата

эээ ну в С++ стандарте насчет подобных примеров было ясно сказано, что будет неопределенность

Как раз по поводу С++ здесь все понятно ИМХО
По приоритету операции сначала идет ++ а потом +=. Причем никаких временных переменных нет. Поэтому и получается 1
Если проверять код 
Код

i = 0;
i += ++i; 

то получим 2, что говорит о том, что используется одна область памяти

А вот про это 
Цитата
i = i++ + ++i;
 я согласен smile


tol05, 
Сиба за ссылку и объяснения, буду читать. Мое ИМХО: так писать низзя 
Еще в "Практике программирования" Керниган сказал, что размер в ущерб  понятности ставить не желательно smile

Автор: tol05 3.10.2007, 10:07
Цитата(NikeDeForest @  3.10.2007,  05:52 Найти цитируемый пост)
имхо, это пижонство, которое не оценит тот, кто будет читать твой код.

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

Цитата(Kuvaldis @  3.10.2007,  08:51 Найти цитируемый пост)
Еще в "Практике программирования" Керниган сказал, что размер в ущерб  понятности ставить не желательно

Нужно читать любой код и читать правильно. Поэтому я "за" за существование таких вопросов в тесте.
Нельзя так писать? 
а так
Код

for(int i=0; ; i++)

или
Код

for(int i=0; ; ++i)

можно?
Это читаемо? 
Просто инкремент и декремент выполняются быстрее, чем присваивание. Но вряд ли это кого-от беспокоит, кроме меня.

Вряд ли Керниган имел в виду простейшие констукции smile У меня нет его под рукой, но я думаю, что он имел в виду что-то вроде этого:
Код

if(((MyArray)MyObject.GetValues()[0]).[2][i])...

Да... И напишите письмо в команду разработчиков .Net 2.0, чтобы убрали из новой версии анонимные методы, итераторы и генерики.  smile 

Автор: Rodman 3.10.2007, 10:19
i++ - инкремен происходит после использования переменной! тогда и получается что прибавляется 0, 
Цитата(Kuvaldis @  2.10.2007,  16:08 Найти цитируемый пост)
C точки зрения С++ получается 1, что я и скачал, но правильный ответ - 0

Код

        int i = 0;
        i += i++;
        ShowMessage(IntToStr(i));
я вот в Билдере сделал, у меня 1 получилась!

Автор: Alek86 3.10.2007, 11:16
Цитата(Kuvaldis @  3.10.2007,  08:51 Найти цитируемый пост)
Как раз по поводу С++ здесь все понятно ИМХО
По приоритету операции сначала идет ++ а потом +=. Причем никаких временных переменных нет. Поэтому и получается 1


я бы так не утверждал категорично... в сях есть такая вещь, как "точка следования", и по стандарту += не входит в те операторы, после которых она (точка) ставится.
в С++ результат этого   i += ++i;    выражения неопределен

потому и нужно посмотреть на стандарт C#, что там насчет этого говорится.

Автор: skyboy 3.10.2007, 11:35
Цитата(Kuvaldis @  3.10.2007,  07:51 Найти цитируемый пост)
Как раз по поводу С++ здесь все понятно ИМХО

http://alenacpp.blogspot.com/2005/11/sequence-points.html
Цитата(Alek86 @  3.10.2007,  10:16 Найти цитируемый пост)
потому и нужно посмотреть на стандарт C#, что там насчет этого говорится.

а где можно посмотреть стандарт по С#? Не подскажешь?

Автор: Deja_Vu 3.10.2007, 11:36
Код

    int i = 0;
            i += i++;
            printf("i += i++ : %d\n", i);
            i = 0;
            i = i + i++;
            printf("i = i + i++ : %d\n", i);
            i = 0;
            i = i + ++i;
            printf("i = i + ++i : %d\n", i);
    getch();

Код

i += i++ : 1
i = i + i++ : 1
i = i + ++i : 2


Код

            int i = 0;
            i += i++;
            Console.WriteLine("i += i++ : {0}", i);
            i = 0;
            i = i + i++;
            Console.WriteLine("i = i + i++ : {0}", i);
            i = 0;
            i = i + ++i;
            Console.WriteLine("i = i + ++i : {0}", i);
            Console.ReadLine();

Код

i += i++ : 0
i = i + i++ : 0
i = i + ++i : 1

Автор: skyboy 3.10.2007, 11:44
Цитата(skyboy @  3.10.2007,  10:35 Найти цитируемый пост)
а где можно посмотреть стандарт по С#

http://www.ecma-international.org/publications/standards/Ecma-334.htm, 2.5 Мб
Вот только с английским не настолько дружу, чтоб сходу найти нужный раздел...

Автор: Alek86 3.10.2007, 13:27
пара оффтопов

Deja_Vu, насчет С++ еще раз - там неопределенность! если кто-то будет говорить иначе, посылай читать стандарт


skyboy, насчет ссылки  про точки следования - smile 
сам почитываю ее блог иногда smile

Автор: ivashkanet 3.10.2007, 13:32
Цитата(Deja_Vu @  3.10.2007,  11:36 Найти цитируемый пост)
i = i + i++ : 1

Меня интересует почему в С++ здесь единица, а не ноль?

Добавлено через 43 секунды
Все потому что неопределённость?

Автор: Deja_Vu 3.10.2007, 13:35
Цитата(Alek86 @ 3.10.2007,  13:27)
Deja_Vu, насчет С++ еще раз - там неопределенность! если кто-то будет говорить иначе, посылай читать стандарт

я что-то увтерждаю?! ((-
Я просто привожу результат компиляция на VS 2008. 

В MSDN и в спецификации ничего по этому поводу найти не могу... остается
 всего одно предположение

i = i + i++;

1. вычисляется выражение i + i
2. выполняется операция i++
3. выполняется присваивание i = результату(1)


Добавлено @ 13:44
да уж ...
Код

 i = 1 + (i++)*100  ;
Console.WriteLine("i = 1 + (i++)*100 : {0,2}", i);


Код

i = 1 + (i++)*100 : 1

 smile 

Автор: tol05 3.10.2007, 14:01
нашел неплохой источник информации по данной проблеме http://www.google.com/search?hl=en&rlz=1T4GGLJ_enUA238UA238&q=increment+C%2B%2B+C%23+differences
 smile 


Автор: Deja_Vu 3.10.2007, 14:17
sorry -))

Автор: Fazil6 3.10.2007, 14:24
Цитата(ivashkanet @  3.10.2007,  13:32 Найти цитируемый пост)
Меня интересует почему в С++ здесь единица, а не ноль?

не в С++, а в программе, скомпиллированной определенным компиллятором определенной версии. Как сделали разработчики порядок и логику вычислений, так ты и получил. На другой версии компиллятора ты можешь получить другое значение, например 24 и ошибкой это не будет. Как говорится что написал - то и получил. Написал выражение правила вычисления которого не существует - то и получай в результате что угодно.

Автор: Deja_Vu 3.10.2007, 14:30
Цитата(Deja_Vu @ 3.10.2007,  13:35)
 всего одно предположение

i = i + i++;

1. вычисляется выражение i + i
2. выполняется операция i++
3. выполняется присваивание i = результату(1)


thx to tol05
оказываетя мое предположение верно.
http://weblogs.asp.net/kennykerr/archive/2006/03/29/Increment-differences-in-C_2B002B00_-and-C_2300_.aspx

Автор: ivashkanet 3.10.2007, 14:52
Цитата(Fazil6 @  3.10.2007,  14:24 Найти цитируемый пост)
не в С++, а в программе, скомпиллированной определенным компиллятором определенной версии

Я это знаю smile 
Цитата(Fazil6 @  3.10.2007,  14:24 Найти цитируемый пост)
Написал выражение правила вычисления которого не существует - то и получай в результате что угодно. 

Это я и имел ввиду

Спасибо ;-)

Автор: Alek86 3.10.2007, 16:01
Цитата(Deja_Vu @  3.10.2007,  14:30 Найти цитируемый пост)
оказываетя мое предположение верно.Описание нашей проблемы


[/quote=Как раз с той ссылки]At the end of the day the C# compiler results in a value of 1 and the C++ compiler results in a value of 2. Neither is right, neither is wrong and both are undefined.[/quote]

так что не совсем верно smile

а в шарпе в стандарте я чето не нашел никаких правил :(.
думается мне, что там все считается по-порядку

к тому же я знаю только одну версию компилятора C#, написанную майкрософтом

ЗЫ. кстати, под линух компилятор (а не среда исполнения Mono) существует?

Автор: Deja_Vu 3.10.2007, 23:09
Цитата(Alek86 @ 3.10.2007,  16:01)
Цитата(Как раз с той ссылки)
At the end of the day the C# compiler results in a value of 1 and the C++ compiler results in a value of 2. Neither is right, neither is wrong and both are undefined.

так что не совсем верно smile

ну ... что правильно, и не правильно не мне решать ... но то как действует компилятор C# от MS описано то мною верно -))

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)