LINUX.ORG.RU
ФорумTalks

i += i++ + ++i


0

1

Привет.

Я тут случайно узнал что следующий код дает разный результат для разных языков. Всю жизнь был уверен что оно работает одинаково кругом, и возвращает 4.

// i -- целочисленная переменная
i = 0;
i += i++ + ++i;
// чему равно i?

Так в C, Perl, PHP оно выводит 4, в Java, Javascript же 2. Причину я понял (момент вычисления i++), но зачем они такое сделали??? И еще вопрос. Есть ли гарантия что все реализации Java (JVM и компилятора) дадут 2?

☕☕☕☕☕

>>но зачем они такое сделали???

Чтобы над плюсистами можно было поглумиться.

MuZHiK-2
()

> Я тут случайно узнал

Век живи - век учись.

Не надо в одном выражении читать и изменять одну и ту же переменную. Даже если какой-то язык в каких-то случаях и даёт какие-то гарантии на этот счёт, у людей всё равно мозги будут пухнуть от такого выпендрёжа.

const86
()
Ответ на: комментарий от const86

Да я понимаю что такой код никто не пишет, кроме школьников, чтобы повые перед учителем. Но вопрос тут не в том.

urxvt ☕☕☕☕☕
() автор топика

Хм... скажите, а я правильно понимаю, что сначала вычисляется ++i и i становится равно единице, конструкция i++ + ++i принимает вид 2 + 1, и к i, которое уже приняло значение 1, прибавляется 3 и получается 4?

Ramen
()

Гарантий никогда нет.

Есть ли гарантия что все реализации Java (JVM и компилятора) дадут 2?

Я читал про Jav'у, таки там выводили что должно быть 2 не экспериментом, а именно из документации. Так что все корректные реализации Jav'ы должны давать 2, но кто гарантирует корректность реализации?

Camel ☕☕☕
()
Ответ на: комментарий от xetf

Пруфлинка нет.

Зависит от реализации. В стандарте поведение в таком случае не определено.

Хм. Где-то я читал разбор этой штуки как раз по стандарту. Почему в C будет 4 (внимательно изучали указатели) и почему в Java — 2.

Camel ☕☕☕
()

Я тут случайно узнал что следующий код дает разный результат для разных языков

Оно еще и на разных компиляторах может выдать разные значения.

Andru
()

Пиши код нормально и будет тебе гарантия.

nu11
()
Ответ на: комментарий от Ramen

>i += i++ + ++i

К нулю прибавляется(i += i) нуль(0), затем нуль увеличивается(i++) на единицу, затем единица увеличивается(++i) ещё на один и прибавляется(+ ++i) к нулю.

wyldrodney
()
Ответ на: Пруфлинка нет. от Camel

>>Зависит от реализации. В стандарте поведение в таком случае не определено.

Хм. Где-то я читал разбор этой штуки как раз по стандарту. Почему в C будет 4 (внимательно изучали указатели) и почему в Java — 2.

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

name_no
()

от компилятора С++ и ключей тоже зависит результат.

matich
()
Ответ на: комментарий от name_no

>>>Зависит от реализации. В стандарте поведение в таком случае не определено.

Хм. Где-то я читал разбор этой штуки как раз по стандарту. Почему в C будет 4 (внимательно изучали указатели) и почему в Java — 2.

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

я конечно говорю про C++, про который спрашивал тот, кому отвечали

name_no
()

Я даже больше скажу. Из трех компиляторов (gcc, MSVS и Borland) какой-то из них тоже выдаст результат 2. Правдя я не помню, это выдаст компилятор толи от борланд толи от МС.

qwertyk
()
Ответ на: комментарий от wyldrodney

>К нулю прибавляется(i += i) нуль(0), затем нуль увеличивается(i++) на единицу, затем единица увеличивается(++i) ещё на один и прибавляется(+ ++i) к нулю.
И получается 2, а не 4.

Ramen
()
Ответ на: комментарий от Ramen

Если я не ошибся в i += i++, то будет 2. Но я не уверен что в этом куске результатом будет 0, а не 1(хрен его знает когда и что i++ возвращает). И я не знаю складывается ли оно по частям, или сначала считается правая часть, а затем прибавляется к левой.

wyldrodney
()
Ответ на: комментарий от name_no

это вообще не должно компилироваться, потому что говнокод.

О мудрейший, скажи, откуда берётся говнокод, если он не компилируется? Говнокодеры специально ищут дыры в компиляторе, чтобы пропихнуть через него свои творения во славу Лакшми?

Xenesz
()

собственно везде четко сказано что подобные конструкции нельзя использовать.

exception13
()

Для Си порядок вычисления (слева направо или наоборот) не определён. Если его уже кто-то зашил в стандарт, то не все компиляторы об этом знают. Так или иначе, это фактически не стандарт, а особенность компилятора.

Xenesz
()

>Есть ли гарантия что все реализации Java (JVM и компилятора) дадут 2?

Читаем про приоритеты выполнения операций, а также с какой стороны они выполняются (банально, если справо налево =4, слева направо =2).

gh0stwizard
()
Ответ на: комментарий от wyldrodney

>Если я не ошибся в i += i++, то будет 2. Но я не уверен что в этом куске результатом будет 0, а не 1(хрен его знает когда и что i++ возвращает). И я не знаю складывается ли оно по частям, или сначала считается правая часть, а затем прибавляется к левой.
Ну я спрашивал, как получается 4. Насколько я понял, считается как раз сначала правая часть, причём в правой части сначала выполняется ++i, тогда получается как раз 4.

Ramen
()
Ответ на: комментарий от urxvt

>>Тебе не интересны такие детали?

Нет, не интересны.

Думаю, они не интересны даже создателям этих компиляторов.

Ибо такие знания не двигают вперёд, а просто описывают техническую особенность конкретной версии.

Это ещё скучнее чем реестр Windows или ключи unrar.

mclaudt
()
Ответ на: комментарий от Xenesz

> О мудрейший, скажи, откуда берётся говнокод, если он не компилируется?

его высирают говнокодеры и он потом не конпелируется.

name_no
()
Ответ на: комментарий от wyldrodney

>>i += i++ + ++i

К нулю прибавляется(i += i) нуль(0), затем нуль увеличивается(i++) на единицу, затем единица увеличивается(++i) ещё на один и прибавляется(+ ++i) к нулю.


Как нам объясняли в универе, это примерно эквивалентно:
++i; //Сначала прединкремент, i=1
t=i+i; //Вычисление значения правого аргумента операции +=, t=2
i++; //Постинкремент, на значение справа уже не влияет, i=2;
i+=t; // Добавление к i значения справа. 2+2 = 4.

unikoid
()

Про i++ + ++i разжёвывали уже много раз. Там для языков с правильно реализованными приоритетами всё однозначно, для Си/Си++ результат не определён согласно стандарту.

А вот вариант ещё и с i += ... - это неопределённость уже на уровне здравого смысла. В конкретном языке могут, наверное, описать такую особенность, но, боюсь, на практике такого нигде нет. Так что - нафиг :)

KRoN73
()
Ответ на: комментарий от xetf

>В стандарте поведение в таком случае не определено.

Не определено, но оговорено: the behavior is unspecified.

KRoN73
()
Ответ на: комментарий от urxvt

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

Если посчитать, сколько секунд сэкономил оператор постинкремента, да вычесть время которое он съел на изучение и обсуждение своих костыльных особенностей, то получится минус много человеколет, (*в сторону) сколько бы не долбался ржавой дилдой новоиспечённый игнораст.

mclaudt
()
Ответ на: комментарий от wyldrodney

>ОМГ, g++ сказал что будет 4.

Почти все Си компиляторы постинкремент переменной проводят после всего вычисления, и преинкремент - перед ним. Но не во время вычисления, как того требует логика приоритетов.

KRoN73
()
Ответ на: комментарий от wyldrodney

>Если я не ошибся в i += i++, то будет 2

Не определено. В стандарте не оговаривается, будет результат прибавляться к исходному или к конечному значению i. Вот в результате Java прибавляет к исходному и получается 2, а Perl/PHP - к конечному, и выходит 4. И тот, и другой подходы по-своему логичны.

KRoN73
()
Ответ на: комментарий от Xenesz

>Для Си порядок вычисления (слева направо или наоборот) не определён.

Определён. С самого начала. По каждому оператору прописан. Для сложения - слева на право.

KRoN73
()
Ответ на: комментарий от gh0stwizard

>Читаем про приоритеты выполнения операций, а также с какой стороны они выполняются (банально, если справо налево =4, слева направо =2).

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

KRoN73
()
Ответ на: комментарий от mclaudt

>А самое главное — эти вещи не прописаны в стандартах

В Java, ЕМНИП, прописано. Хотя пруф искать влом. В Си/Си++ тоже прописано, что результат - не определён.

KRoN73
()
Ответ на: комментарий от wyldrodney

> Проверять не буду специально, а спрошу: в С++ это будет 2?

undefined behavior

Reaper
()

За такой код тебе сейчас Microsoft, на который ты сцыш, яйца оторвет. :)

vada
()

В СТАНДАРТЕ сказано что это оставляется на совесть разработчика.

КСТАТИ В С это равно разным числам в зависимости от опций компилятора и версии компилятора. Я добивался разных результатов с -O0 и -O2

vahvarh
()
Ответ на: комментарий от vahvarh

>Я добивался разных результатов с -O0 и -O2

Совершенно логично. В отсутствии оптимизации инкрементов будет столько, сколько раз они используются, с полной оптимизацией - один.

KRoN73
()
Ответ на: комментарий от Nao

+= приоритетнее чем + ? Что за язык такой чудной?

Меня это тоже удивило. В Си эта операция вообще имеет очень низкий приоритет (самый низкий имеет запятая).

edigaryev
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.