vakito
10:48 11-05-2007
Как себя занять? Правильно, читаем башорг.
Задача.
i=5;
i = ++i+ ++i;
i=?

Ява выдает 13, С++ 14, камрад Xirax говорит, что php выдает 13.
Вопрос: почему разный результат?
Комментарии:
cpcat
11:34 11-05-2007
Разная очерёдность выполнения. Если не ошибаюсь, это есть в любом современном учебнике программирования, или справочнике по языку.
davvol
12:44 11-05-2007
Потому что Ява и Пхп обрабатывают строки сразу и последовательно, а Си обрабатывает их целиком, и у него приоритет инкримента выше чем приоритет сложения.
Вот от этого и разный результат.
vakito
13:47 11-05-2007
cpcat davvol
а сколько тогда будет i++ + i++?
cpcat
14:20 11-05-2007
В сях вроде 12, в скриптах - не знаю
vakito
14:25 11-05-2007
cpcat
в яве 11
cpcat
15:50 11-05-2007
Бля.

int main()
{
int i = 5;
int n = 5;

i = ++i+ ++i;
printf("i = %d\n", i);

n = n++ + n++;
printf("n = %d\n\n", n);

}

$ cc test.c
$ ./a.out
i = 14
n = 12
Anafay
17:58 11-05-2007
Господа, не ругайтесь. В С (и, скорее всего, в С++ тоже) есть такое понятие как sequence point. Инкременты и сложение к ним не относятся, так что результат зависит от трактовки конкретным компилятором.
Zanokra
19:51 11-05-2007
а если ++i взять в скобки, то одинаковый ответ будет?
Anafay
20:17 11-05-2007
Zanokra
Нет, поскольку не определен точно момент времени, когда переменной i будет присваиваться значение i+1. Замени ++i на (i+=1) для наглядности.

C99, 6.5.3.1, Prefix increment and decrement operators:
The expression ++E is equivalent to (E+=1).

C99, 6.5.16, Assignment operators:
The side effect of updating the stored value of the left operand shall occur between the previous and the next sequence point.

Варианты ответов, для разных компиляторов и разных вариантов оптимизации: 6,7,12,13,14.
Zanokra
20:51 11-05-2007
Anafay что-то не пойму. как не определен?
i=5
i=(++i)+ (++i)
=(6)+(7)
=13

как иначе?
какая я глупая
Anafay
21:08 11-05-2007
Zanokra
При использовании ++i значение этого выражения равно i+1. Но когда это будет записано в i, сказать нельзя. Смотри разные трактовки:

Результат 14:
i=(i+=1), (i+=1), (i+i);

Результат 13:
i=(c=i+1), (i=c), (i+=1), (i+c);

Результат 12:
i=(c=i+1), (d=i+1), (i=c), (i=d), (c+d);

Результат 6:
i=(c=i+1), (d=i+1), (i=d), (i+i);
i=c;

Результат 7:
i=(c=i+1), (i=c), (d=i+1), (i+i);
i=d;
vakito
21:13 11-05-2007
Anafay
интересно, вариант на 6 и на 7 где-нибудь реально используется?
жаль в абапе нет таких фишек...
Zanokra
21:13 11-05-2007
Anafay аа. я забыла, что это i и присваивается.) тогда понятно.
vakito
21:16 11-05-2007
Zanokra
это не важно.
если напишешь в сях j = ++i+ ++i, результат все равно будет 14.
Zanokra
21:17 11-05-2007
а зачем вообще ++, если такие сложности? лучше лишнюю строчку написать)
Anafay
21:18 11-05-2007
vakito
интересно, вариант на 6 и на 7 где-нибудь реально используется?
Gnu и иже с ними?
Там полно софта, который собирается только конкретной версией компилятора и только с определенными опциями.

жаль в абапе нет таких фишек...
А теперь представь себе, что тебе надо саппортить код, в котором полно подобного. Даже простой переезд на новую версию компилятора представляет собой засаду
Anafay
21:20 11-05-2007
vakito
j = ++i+ ++i

j=++i + ++k;
vakito
21:23 11-05-2007
Zanokra
я видел, как пишут классные коды именно с этими фишками. Только разобраться потом невозможно, но работает!
Anafay
Gnu и иже с ними?
жаль проверить мне негде. но в возможность присваивания результата инкремента после сложения верится с трудом...
Даже простой переезд на новую версию компилятора
как же мы по шестерке облизываемся....
а засад с переездом с версии на версию и так вагон
Zanokra
21:23 11-05-2007
vakito
если напишешь в сях j = ++i+ ++i, результат все равно будет 14.
ну да, 13 не получится
vakito
21:24 11-05-2007
Anafay
j=++i + ++k;
ну тогда да, конечно. но это уже неинтересный случай.
vakito
21:27 11-05-2007
Zanokra
так. 13 в яве, 14 в сях, если j = ++i+ ++i
Zanokra
21:27 11-05-2007
vakito Только разобраться потом невозможно, но работает!
а если неправильно?
Zanokra
21:27 11-05-2007
vakito так. 13 в яве, 14 в сях, если j = ++i+ ++i
значит моя логика написана на яве)

я киборг
vakito
21:30 11-05-2007
Zanokra
а если неправильно?
ну автор кода разберется
Anafay
21:32 11-05-2007
vakito
так. 13 в яве, 14 в сях, если j = ++i+ ++i
Буду настаивать, что не 14, а от 12 до 14
Zanokra
21:37 11-05-2007
http://programming.reddit.com/info/1po78/comments
vakito
21:40 11-05-2007
Anafay
ну я без выпендрежей имею в виду
Anafay
21:43 11-05-2007
vakito
Оно так и будет. Когда пишешь, то думаешь о том, что должно получиться в итоге. А тут итог - 12, 13 и 14. По стандарту иначе не выходит.
vakito
21:44 11-05-2007
Anafay
порадовало:
Writing ++i + ++i could start launch missiles, or something, who knows?
sentaus
01:32 12-05-2007
"Не насилуйте язык попытками его причудливого использования." (c)Дейтел&Дейтел // Как программировать на C++
sentaus
01:38 12-05-2007
Или вот совсем простое:
{
int i = 0;
i = i++;
}

{
int i = 0;
i = ++i;
}

Что будет в первом случае, и что во втором?
Zanokra
02:39 12-05-2007
sentaus не определено в обоих случаях, да? или только в первом?

пошла читать про sequence point...

отредактировано: 12-05-2007 04:39 - Zanokra

vakito
11:15 12-05-2007
sentaus
да таже фигня, зависящая от компилятора.
sentaus
19:15 12-05-2007
В C/C++ Undefined в обоих случаях. Но, если я не ошибаюсь, во втором случае получится всегда 1 - вне зависимости от порядка действий. По хорошему на таких вещах нужно в error падать, даже не в warning.
vakito
19:43 12-05-2007
sentaus
ну да, во втором так или иначе единица
sentaus
00:24 13-05-2007
Можно продолжить извраты

#include <iostream>
#include <cstdlib>

using namespace std;


void first()
{
int i = 5;
i = ++i + ++i;
printf("1:i=%d\n", i);
}


int myinc(int &i)
{
return ++i;
}

void second()
{
int i = 5;
i = ++i + ++i;
printf("1:i=%d\n", i);
i = 5;
i=myinc(i)+myinc(i);
printf("2:i=%d\n", i);
}



int main(int argc, char *argv[])
{
printf("Fisrt\n");
first();
printf("Second\n");
second();
return EXIT_SUCCESS;
}

Компилируем в gcc -O0 и получаем:
Fisrt
1:i=14
Second
1:i=13
2:i=13
Zanokra
00:26 13-05-2007
ну да, во втором так или иначе единица
а в первом нет? сначала присваивается 0, потом увеличивается на один..
vakito
05:04 13-05-2007
Zanokra
в первом нет. Может сначала присвоиться ноль, а потом увеличивается i на 1. Но присвоенный ноль сохраняется. Плюсы справа.
Zanokra
05:28 13-05-2007
vakito потом увеличивается i на 1. Но присвоенный ноль сохраняется
как так?
sentaus
11:05 13-05-2007
Я ещё выше привел программу, где компилятор в двух местах компилирует одинаковый код различными способами.

отредактировано: 13-05-2007 14:02 - sentaus

vakito
16:50 13-05-2007
Zanokra ну как? i=i++
Сначала присвоение, потом увеличение без сохранения.
vakito
16:53 13-05-2007
sentaus
почему 1ый случай секонда так работает? (не 14)
IrUsJA Backsey inc
17:44 13-05-2007
vakito О!!я наю...i = i + (-i) + i....кацца не забыла математику...
vakito
18:13 13-05-2007
Rina
так. стоп. математика не при чем. речь о программировании.
sentaus
18:33 13-05-2007
Хороший вопрос

Компиляция в режиме O0
first:
// int i = 5;
movl $5, -4(%rbp)
//i = ++i + ++i;
addl $1, -4(%rbp)
addl $1, -4(%rbp)
movl -4(%rbp), %eax
addl %eax, -4(%rbp)

second:
// int i = 5;
movl $5, -12(%rbp)
//i = ++i + ++i;
movl -12(%rbp), %eax
addl $1, %eax
movl %eax, -12(%rbp)
movl -12(%rbp), %edx
movl -12(%rbp), %eax
addl $1, %eax
movl %eax, -12(%rbp)
movl -12(%rbp), %eax
leal (%rdx,%rax), %eax
movl %eax, -12(%rbp)

В общем, во втором случае компилятор повёл себя по-джавному. Примечательно, что в режиме O2 код обоих фрагментов абсолютно идентичен и занимает всего одну инструкцию
movl $14, %esi
vakito
23:23 13-05-2007
sentaus
я в этом плохо разбираюсь. В абапе же нет всего этого.
На пальцах расскажи.
sentaus
23:53 13-05-2007
В общем, это практический пример. Anafay теорию уже всю рассказал.
Zanokra
23:56 13-05-2007
vakito ну как? i=i++
Сначала присвоение, потом увеличение без сохранения.

хехе, увеличивает ту и, что справа?
IrUsJA Backsey inc
23:58 13-05-2007
Оооооооооооооооооо!!!!!
vakito
00:00 14-05-2007
Zanokra
ты вот файл сначала изменяешь, а потом сохраняешь. Изменения сохраняются. А можно сохранить, а потом изменить -- изменения пропадут. Так и тут.
Zanokra
00:01 14-05-2007
ааа!
sentaus
00:01 14-05-2007
Rina
Это не ОООООО, а O-нуль.