опять подменили x++
x++ - это постфиксное выражение, у них свои свойства
++x - это одноместное выражение, у них свои свойства
и x++ + x++ в сравнении с ++x + ++x совсем по-разному работают
каким образом ++x + ++x + ++x может выполнится по-другому и получатся разные результаты в разных компиляторах (это из первого вопроса всё) ?
префиксный инкремент
Модератор: Модераторы разделов
-
- Сообщения: 8735
- Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
- ОС: Slackware-current
Re: префиксный инкремент
вы наверное довольно молоды

это одна и та-же операция, раньше все регистры CPU такое допускали, сейчас, правда, только esp так может. постфиксные и префиксные операции очень удобны для индексной арифметики, которая и используется в С и в С++ - разные алгоритмы поиска, сортировки, и прочего, что в других языках спрятано в библиотеках и разных регулярных выражениях. Без этих операций даже простейший стек не сделать, точнее можно, только работать будет в два раза дольше.
Код: Выделить всё
void push(int x)
{stack[++sp] = x;}
int pop()
{return stack[sp--];}
каждая из этих функций, во времена создания Си, превращалась компилятором в 1 команду процессора. так в языке это и осталось... Если вы думаете, что x++ выполняется как
Код: Выделить всё
tmp = x;
x = x+1;
return tmp;
вы сильно заблуждаетесь, это не bash

-
- Сообщения: 296
- ОС: fedora, mandriva
Re: префиксный инкремент
(drBatty) писал(а):это одна и та-же операция
а её результат ? он выходит за её пределы ?
-
- Сообщения: 8735
- Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
- ОС: Slackware-current
Re: префиксный инкремент
конечно! вопрос - когда.
вы почему-то полагаете, что
1)сначала выполняются ++,
2)а потом берётся результаты,
3)а потом складывается.
Но это не так. Нет такого требования в стандарте.
возможно такое:
1)сначала выполняется один из ++
2)берётся его результат(6)
3)потом выполняется второй ++
4)берётся его результат(7)
5)складывается, ответ 13
или
1)компилятор решает копирует x в х2
2)выполняется первый ++х, и берётся его результат(6)
3)выполняется второй ++х2, и берётся его результат(6)
4) сумма равна 12
Этот вариант хорош, если у нас 2 ALU, а начиная с Pentium1 это так везде. Можно п2 и п3 выполнить за 1 такт в U и в V трубе. Правда есть ещё п1, но его мы можем совместить с почти любой другой операцией, вот только с п4 не получится совместить(а первом пне, в новых может быть и получится). Даже странно, почему получается именно 14, а не 12! (на наших компиляторах)

PS: в данном случае у выражения есть 2 результата:
1)сама сумма, непонятно какая(12,13,14)
2)новое значение x, оно равно в точности 7.
Компилятор обязан вычислить оба, причём второе он обязан вычислить правильно. Потому семёрка получится обязательно. Что касается суммы, то компилятор просто удваивает эту семёрку. Думать о результате суммы компилятор не обязан, ему важно получить 7, вот он и оптимизирует два ++ в одно +2(по времени это столько-же, на нынешних CPU). Те варианты где получается 12 или 13 требуют двух инкрементов, а это всё-же дольше одного сложения, даже в случае если инкременты распаленны(второе сложение нельзя спарить не с чем, так-как оно объеденяет результаты с двух конвейров).
Код: Выделить всё
add eax, 2
mov ecx, eax
add eax, ecx
это занимает 3 такта, однако на другом ALU за те-же 3 такта может быть выполнены другие 3 команды.
последовательность
Код: Выделить всё
mov eax, ecx
inc eax
inc ecx
add eax, ecx
тоже выполнится за 3 такта, однако только первая команда может с чем-то спарится.
вторая уже спарена с третий, а четвёртая не спарена не с чем. да и x'ы у нас получились 2 штуки по 6, а нам нужен 1 по 7

вариант когда 13 получится анализируйте сами

Спасибо сказали:
-
- Сообщения: 296
- ОС: fedora, mandriva
Re: префиксный инкремент
а, ну ясно терь
операция + может выполняться разными способами, а не одним
и это при одинаковой последовательности вычисления своих операндов
операция + может выполняться разными способами, а не одним
и это при одинаковой последовательности вычисления своих операндов
-
- Сообщения: 8735
- Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
- ОС: Slackware-current
Re: префиксный инкремент
не, + только одним способом. а вот ++ - двумя, так-как ++ имеет 2 результата, а не один.
ЗЫЖ когда создавали C, были компы PDP, я на таких даже работал(хотя я тогда ещё кроме бэйсика ничего не умел, и в школе учился), там это делалась за 2 команды:
mov R2, INCREMENT:[R1]
add R2, INCREMENT:[R1]
и получалось у отцов основателей именно 13(а я уверен, что про эту фишку они знали)

ЗЗЫЖ про асм - чисто мои предположения, может это и не совсем так. я точно знаю только 2 вещи:
1)компилятор придерживается стандарта, а в стандарте ++ и + не упомянуты как точки следования, значит компилятор может как угодно считать.
2)если точки следования нет, то её надо сделать:
Код: Выделить всё
++x, ++x;
y=x+x;
такой код будет давать 14 на любом компе.
-
- Сообщения: 126
- ОС: archlinux
Re: префиксный инкремент
В общем, нужно стараться не использовать такого рода конструкции, в которых могут возникать неопределенности.
маленький кавайный линуксоид ^_^