префиксный инкремент

Модератор: Модераторы разделов

Аватара пользователя
trinimak
Сообщения: 126
ОС: archlinux

префиксный инкремент

Сообщение trinimak »

К примеру:
{
int x=5;
x=++x + ++x;
cout << x;
}
На С++ у меня получилось 14. Но в разных языках разное число получается.
По идеи оператор ++х увеличивает исходное значение на единицу, получатся 6, ну и 6 + 6 = 12 как я понимаю, но видимо я не правильно понимаю.
Кто нибуть может объяснить почему 14?
маленький кавайный линуксоид ^_^
Спасибо сказали:
Аватара пользователя
AestheteAnimus
Сообщения: 135
ОС: FreeBSD 8.0-RELEASE amd64

Re: префиксный инкремент

Сообщение AestheteAnimus »

Схема выполнения примерно такая:
1. ++x, ++x (6, 7)
2. x = x + x (7 + 7 = 14)

А что собственно смущает? И какой смысл это проверять синтаксисом других языков?!
Спасибо сказали:
Аватара пользователя
trinimak
Сообщения: 126
ОС: archlinux

Re: префиксный инкремент

Сообщение trinimak »

Нет ни чего не смущает. Просто недавно начал изучать С++ и не совсем понял как в данном примере проходит вычисление. Я лично не проверял, в гугле нашел, что в разных языках разный результат =)
маленький кавайный линуксоид ^_^
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: префиксный инкремент

Сообщение drBatty »

trinimak писал(а):
08.04.2009 22:23
Просто недавно начал изучать С++ и не совсем понял как в данном примере проходит вычисление.
на усмотрение компилятора.
по стандарту, насколько я знаю, результат не определён. Это старый трюк... Кстати, в C вовсе не обязательно 14, зависит от компилятора и от CPU.
да, a+b+c тоже вычисляется на усмотрение компилятора, может (a+b)+c, а возможно a+(b+c)
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
nesk
Сообщения: 2268
Статус: Линукссаксовец
ОС: MS Windows XP Home SP3

Re: префиксный инкремент

Сообщение nesk »

drBatty писал(а):
08.04.2009 22:39
да, a+b+c тоже вычисляется на усмотрение компилятора, может (a+b)+c, а возможно a+(b+c)


а что от перемены мест слагаемых сумма меняется?
А у операции префиксный инкремент приоритет больше чем у просто сложения.

Про порядок вычисления операций в C++ (и C) можно почитать например тут: http://www.intuit.ru/department/pl/cpp/3/3.html
Внимание: У меня под рукой нет машины с Linux. Я не использую эту ОС. Ответы я даю либо по памяти, либо мне помогает гугл. Тщательно читайте маны по тем командам и конфигурационным файлам, которые я упоминаю.

0xDEFEC8ED
Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5413
ОС: Gentoo

Re: префиксный инкремент

Сообщение /dev/random »

Возможные последовательности (в обратной польской нотации):
1) x->, ++, x<-, x->, ++, x<-, x->, x->, +, x<- (14)
2) x->, ++, x<-, x->, x->, ++, x<-, x->, +, x<- (13)
и даже
3) x->, x->, ++, x<-, ++, x<-, x->, x->, +, x<- (12)

И вообще. Эти 2 ++'а не разделены точкой следования. Значит, компилятор имеет право выполнить их даже параллельно, в разных потоках! (я таких не видел, но стандарт допускает). А что бывает когда пытаются параллельно выполнить 2 ++'а, я думаю, все тут знают.
Спасибо сказали:
Аватара пользователя
pluton8
Сообщения: 108
ОС: Arch GNU/Linux

Re: префиксный инкремент

Сообщение pluton8 »

аналогичное обсуждение было тут: http://wasm.ru/forum/viewtopic.php?id=20504
THE TRUTH IS OUT THERE
Linux Registered User #450136
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: префиксный инкремент

Сообщение drBatty »

nesk писал(а):
08.04.2009 23:21
а что от перемены мест слагаемых сумма меняется?
а что такое operator+() ?
я этого не написал. может он выполняет перефиксное умножение? ;)
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: префиксный инкремент

Сообщение drBatty »

/dev/random писал(а):
09.04.2009 00:04
Значит, компилятор имеет право выполнить их даже параллельно, в разных потоках! (я таких не видел, но стандарт допускает). А что бывает когда пытаются параллельно выполнить 2 ++'а, я думаю, все тут знают.

думаю, что всё будет хорошо:

Код: Выделить всё

x1 = 5 | x2 = 5
++x1   | ++x2
      x1+x2

ответ: 12
если конечно у нас есть 2 процессора, и у каждого есть своя память для хранения х1 и х2
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
nesk
Сообщения: 2268
Статус: Линукссаксовец
ОС: MS Windows XP Home SP3

Re: префиксный инкремент

Сообщение nesk »

drBatty писал(а):
09.04.2009 10:17
а что такое operator+() ?

Мы говорим про конкретный язык программирования. Там нет такого операции. Там есть () которые меняют порядок выполнения операций и есть операция +
Если Вы изобретите свой язык программирования, можете придумывать там любые операции.

ответ: 12
если конечно у нас есть 2 процессора, и у каждого есть своя память для хранения х1

Вот только загвоздка в том, что ответ должен был быть 14
Внимание: У меня под рукой нет машины с Linux. Я не использую эту ОС. Ответы я даю либо по памяти, либо мне помогает гугл. Тщательно читайте маны по тем командам и конфигурационным файлам, которые я упоминаю.

0xDEFEC8ED
Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5413
ОС: Gentoo

Re: префиксный инкремент

Сообщение /dev/random »

nesk писал(а):
09.04.2009 12:03
Вот только загвоздка в том, что ответ должен был быть 14

Нет никакого "должен быть". Ничего он не должен. Стандарт описывает данную ситуацию как неопределённую.
Спасибо сказали:
Аватара пользователя
deninok
Сообщения: 585
Статус: Программист С++
ОС: Debian GNU/Linux

Re: префиксный инкремент

Сообщение deninok »

(trinimak) писал(а):К примеру:
...
x=++x + ++x;
...
Кто нибуть может объяснить почему 14?

Если вам интересен чисто академический аспект вычисления подобного выражения, тогда ясно. Однако в практическом (реальном) программировании таких выражений нужно просто избегать (всегда). Вот и вся мудрость. :)
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: префиксный инкремент

Сообщение drBatty »

trinimak писал(а):
08.04.2009 21:56
На С++ у меня получилось 14

nesk писал(а):
09.04.2009 12:03
Мы говорим про конкретный язык программирования. Там нет такого операции. Там есть () которые меняют порядок выполнения операций и есть операция +

вы не правы. речь про С++, а там только такая и есть. И скобки порядок тоже не определяют... Вот запятая - определяет.

Код: Выделить всё

int main()
{
    int x = 5;
    int y;
    ++x, ++x, y = x+x;
    printf("%d\n", y);
    return 0;
}

вот тут порядок определён, и ответ 14. А в выше приведённых примерах может получится всё что угодно(хоть 100).
nesk писал(а):
09.04.2009 12:03
Вот только загвоздка в том, что ответ должен был быть 14

откуда такая уверенность??

ЗЫЖ в С++ есть жёсткие правила, но они вовсе не интуитивно понятны:
что такое a+(b+c) можно понять только зная что такое a,b,c и как в них определён метод operator+(), да и после этого не известно, в каком именно порядке будет всё это выполнятся. инкремент - это та-же самая история с побочными эффектами: ++ не только увеличивает на 1, но ещё и возвращает значение. Как увеличивает и какое значение возвращает - ясно, вот только непонятно, в каком порядке это происходит.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
nesk
Сообщения: 2268
Статус: Линукссаксовец
ОС: MS Windows XP Home SP3

Re: префиксный инкремент

Сообщение nesk »

drBatty писал(а):
09.04.2009 14:42

Код: Выделить всё

int main()
 {
     int x = 5;
     int y;
     ++x, ++x, y = x+x;
     printf("%d\n", y);
     return 0;
 }

вот тут порядок определён, и ответ 14. А в выше приведённых примерах может получится всё что угодно(хоть 100).
nesk писал(а):
09.04.2009 12:03
Вот только загвоздка в том, что ответ должен был быть 14

откуда такая уверенность??


Как я говорил ранее в Си определен порядок выполнения операций.
У операции "префиксное увеличение на единицу" приоритет выше чем у "+"
А так же "Если же операции одного и того же приоритета, они выполняются слева направо. "
исходя из этих правил, в выражении
++x + ++x
порядок вычисления будет: ++, ++, +

(1)_(3)_(2)
++x + ++x

Но если стандарт говорит, что ситуация неопределённая, значит так оно и есть :) будем верить стандарту и не будем использовать такой кривой код.

если конечно у нас есть 2 процессора, и у каждого есть своя память для хранения х1 и х2

А если память общая?
То помимо нарушенной вами информационной зависимости, будет еще и конкурунционная зависимость и в этом случае результат параллельного счета вообще непредсказуем и может быть разным при запусках одной и той же программы с одними и теме же начальными данными.
Внимание: У меня под рукой нет машины с Linux. Я не использую эту ОС. Ответы я даю либо по памяти, либо мне помогает гугл. Тщательно читайте маны по тем командам и конфигурационным файлам, которые я упоминаю.

0xDEFEC8ED
Спасибо сказали:
Аватара пользователя
nesk
Сообщения: 2268
Статус: Линукссаксовец
ОС: MS Windows XP Home SP3

Re: префиксный инкремент

Сообщение nesk »

drBatty писал(а):
09.04.2009 14:42
++ не только увеличивает на 1, но ещё и возвращает значение. Как увеличивает и какое значение возвращает - ясно, вот только непонятно, в каком порядке это происходит.

++x сначала увеличивает, потом возвращает
x++ сначала возвращает, потом увеличивает

выражение
x=5
y= ++x + x++


по логике должно вернуть y=12 и x=7
Внимание: У меня под рукой нет машины с Linux. Я не использую эту ОС. Ответы я даю либо по памяти, либо мне помогает гугл. Тщательно читайте маны по тем командам и конфигурационным файлам, которые я упоминаю.

0xDEFEC8ED
Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5413
ОС: Gentoo

Re: префиксный инкремент

Сообщение /dev/random »

nesk писал(а):
09.04.2009 14:57
Как я говорил ранее в Си определен порядок выполнения операций.
У операции "префиксное увеличение на единицу" приоритет выше чем у "+"
А так же "Если же операции одного и того же приоритета, они выполняются слева направо. "
исходя из этих правил, в выражении
++x + ++x
порядок вычисления будет: ++, ++, +

Угу. Вот только этот порядок не определяет, что нужно суммировать.
Возможны такие ситуации:
1) Увеличить х на 1 (6), увеличить х на 1 (7), сложить х и х (14)
2) Увеличить х на 1 (6) и вернуть значение икса для последующего сложения, увеличить х на 1 (7) и вернуть значение икса для последующего сложения, сложить возвращённые значения (13)
и многие другие. Порядок вычисления операций не нарушается ни в одном из этих случаев.

Кроме того, определён лишь порядок вычисления _операций_, а не _операндов_. Порядок вычисления операндов определён лишь для операций "," и ":?". И слагаемые, как я уже говорил, могут вычисляться хоть параллельно. Тем, кто не понял или до сих пор считает иначе, гуглить на тему "точки следования".
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: префиксный инкремент

Сообщение drBatty »

nesk писал(а):
09.04.2009 14:57
Как я говорил ранее в Си определен порядок выполнения операций.
У операции "префиксное увеличение на единицу" приоритет выше чем у "+"
А так же "Если же операции одного и того же приоритета, они выполняются слева направо. "
исходя из этих правил, в выражении
++x + ++x
порядок вычисления будет: ++, ++, +
вовсе нет. компилятор только обязан обеспечить то, что результат ++ попадёт в сложение, но в каком порядке он будет это всё делать - не оговаривается. Конечно людям проще сначала посчитать части выражение, а потом считать целиком, однако для компьютеров это не так... Кроме того, компилятору допускается переставлять скобки, или вообще их убирать, да и порядок операций тоже на усмотрение компилятора. Например:
a+(b+c)
компилятор может создать для такого выражения код, который вычисляет + в любом порядке. и скобки тут не помогут. Обычно такие выражения считаются с конца на х86, т.е. с последнего оператора, но это только моё наблюдение... В реальном коде необходимо обеспечить, то, что результат будет одинаковый при любом порядке расчётов.

nesk писал(а):
09.04.2009 14:57
А если память общая?
То помимо нарушенной вами информационной зависимости, будет еще и конкурунционная зависимость и в этом случае результат параллельного счета вообще непредсказуем и может быть разным при запусках одной и той же программы с одними и теме же начальными данными.
конечно :(
потому за такой код надо руки отрывать с корнем :)

UPD: проверил - мой c++ всё-таки скобки воспринимает, и порядок учитывает...
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5413
ОС: Gentoo

Re: префиксный инкремент

Сообщение /dev/random »

nesk писал(а):
09.04.2009 15:39
выражение
x=5
y= ++x + x++


по логике должно вернуть y=12 и x=7

Не обязательно. Как я уже говорил, порядок вычисления слагаемых для дальнейшего суммирования может быть любым.
Спасибо сказали:
Аватара пользователя
nesk
Сообщения: 2268
Статус: Линукссаксовец
ОС: MS Windows XP Home SP3

Re: префиксный инкремент

Сообщение nesk »

да уж. грустная картина получается
x=5
y=++x + ++x + ++x + ++x
в итоге у=31
:unsure:

7+7+8+9


дальше интересней

x=5
y=++x + ++x + x++
y= 8 + 8 + 5 = 21

x=5
y=++x + x++ + ++x
получается y=19 x=8 вообще не понятно как.
Внимание: У меня под рукой нет машины с Linux. Я не использую эту ОС. Ответы я даю либо по памяти, либо мне помогает гугл. Тщательно читайте маны по тем командам и конфигурационным файлам, которые я упоминаю.

0xDEFEC8ED
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: префиксный инкремент

Сообщение drBatty »

nesk писал(а):
09.04.2009 16:09
y=++x + ++x + ++x + ++x
вы к турниру на непонятное программирование готовитесь? ;)

PS:
x++ + ++x смотрится красивее :)
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
nesk
Сообщения: 2268
Статус: Линукссаксовец
ОС: MS Windows XP Home SP3

Re: префиксный инкремент

Сообщение nesk »

drBatty писал(а):
09.04.2009 16:24
x++ + ++x смотрится красивее :)

Это красиво, но просто
x=5
y=x++ + ++x
y=12

хотя уже понятно, что не везде и не всегда
Внимание: У меня под рукой нет машины с Linux. Я не использую эту ОС. Ответы я даю либо по памяти, либо мне помогает гугл. Тщательно читайте маны по тем командам и конфигурационным файлам, которые я упоминаю.

0xDEFEC8ED
Спасибо сказали:
Аватара пользователя
Folderx
Сообщения: 296
ОС: fedora, mandriva

Re: префиксный инкремент

Сообщение Folderx »

Код: Выделить всё

int x = 5;
x = ++x + ++x;
cout << x;


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

Re: префиксный инкремент

Сообщение drBatty »

Folderx писал(а):
16.04.2009 00:20
+ не сможет сложить свои выражения, если они не будут вычислен
Начинаем сначала:
operator+(type &) не является точкой следования.
точки следования:

Код: Выделить всё

x++, x++;
x++ ? x++ : x++;
x++ || x++;
x++ && x++;
x++; x++;

вроде-бы ничего не забыл. в остальных случаях порядок вычисления не определён. по стандарту.
в том числе и

Код: Выделить всё

f(x++, x++);

и в результате работы исходного кода может получится 12,13, и 14... или вообще неизвестно что.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
Folderx
Сообщения: 296
ОС: fedora, mandriva

Re: префиксный инкремент

Сообщение Folderx »

да, порядок-то не определён, но что это меняет ?
там только для сложения результатов порядок не определён и очерёдности их предварительного вычисления

операция там ++x, если бы была x++, тогда конечно - у меня 12
Спасибо сказали:
Аватара пользователя
nesk
Сообщения: 2268
Статус: Линукссаксовец
ОС: MS Windows XP Home SP3

Re: префиксный инкремент

Сообщение nesk »

Folderx писал(а):
16.04.2009 00:20
+ не сможет сложить свои выражения, если они не будут вычислены :)


а сколько будет
x=5
y= ++x + ++x + ++x + ++x + ++x
?
И почему?
Внимание: У меня под рукой нет машины с Linux. Я не использую эту ОС. Ответы я даю либо по памяти, либо мне помогает гугл. Тщательно читайте маны по тем командам и конфигурационным файлам, которые я упоминаю.

0xDEFEC8ED
Спасибо сказали:
Аватара пользователя
altwazar
Сообщения: 427
Статус: Zz
ОС: Calculate

Re: префиксный инкремент

Сообщение altwazar »

nesk писал(а):
16.04.2009 07:26
а сколько будет
x=5
y= ++x + ++x + ++x + ++x + ++x
?
И почему?


От 30 до 50. От компилятора зависит.
Спасибо сказали:
Аватара пользователя
nesk
Сообщения: 2268
Статус: Линукссаксовец
ОС: MS Windows XP Home SP3

Re: префиксный инкремент

Сообщение nesk »

altwazar писал(а):
16.04.2009 07:54
От 30 до 50. От компилятора зависит.

Угу. именно так :crazy:

Но вопрос предназначался Folderx'у
Внимание: У меня под рукой нет машины с Linux. Я не использую эту ОС. Ответы я даю либо по памяти, либо мне помогает гугл. Тщательно читайте маны по тем командам и конфигурационным файлам, которые я упоминаю.

0xDEFEC8ED
Спасибо сказали:
Аватара пользователя
Folderx
Сообщения: 296
ОС: fedora, mandriva

Re: префиксный инкремент

Сообщение Folderx »

выполняется операция сложения после того, как вычислены оба её операнда

6, 7
7+7 = 14
8
14+8 = 22
и так далее

в итоге у меня получилось 41, а откуда от 30 до 50 ?
как может получиться 30 ?
Спасибо сказали:
Аватара пользователя
nesk
Сообщения: 2268
Статус: Линукссаксовец
ОС: MS Windows XP Home SP3

Re: префиксный инкремент

Сообщение nesk »

Folderx писал(а):
16.04.2009 10:53
6, 7
7+7 = 14
8
14+8 = 22
и так далее


Ну да, это в конкретном компиляторе, но стандартом не определено.

А вот объясните каким образом вот тут
x=5
y=++x + x++ + ++x


Получилось
y=19 x=8


( я конечно понимаю как, но блин это нелогично, неправильно, и непредсказуемо
Внимание: У меня под рукой нет машины с Linux. Я не использую эту ОС. Ответы я даю либо по памяти, либо мне помогает гугл. Тщательно читайте маны по тем командам и конфигурационным файлам, которые я упоминаю.

0xDEFEC8ED
Спасибо сказали:
Аватара пользователя
grouzen
Сообщения: 120
ОС: LFS, slackware

Re: префиксный инкремент

Сообщение grouzen »

nesk писал(а):
16.04.2009 11:58
А вот объясните каким образом вот тут
x=5
y=++x + x++ + ++x


Получилось
y=19 x=8


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


Так ведь поэтому стандарт и говорит про такой код - undefined behavior.
Спасибо сказали: