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 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.