Operators Precedence

User avatar
thinker
Уже с Приветом
Posts: 26853
Joined: 29 Aug 2000 09:01

Operators Precedence

Post by thinker »

Code: Select all

#include<stdio.h>
int main()
{

    int x = 5;
    int z = x-- * x--;

    printf("x =  %d", x);
    printf("   z = %d", z);

    return 0;
}
Кто-нибудь может объяснить почему результат: x = 3, z = 20 ?
х = 3 понимаю, z = 20 нет.
All rights reserved, all wrongs revenged.
mskmel
Уже с Приветом
Posts: 947
Joined: 24 Sep 2013 05:58
Location: US\GA

Re: Operators Precedence

Post by mskmel »

tau
Уже с Приветом
Posts: 510
Joined: 07 Dec 2001 10:01
Location: toronto

Re: Operators Precedence

Post by tau »

Зависит от компилятора.
Один из моих, к примеру, выдаёт "x = 3 z = 25".
То есть, он настолько умный, что сначала загружает x и умножает его сам на себя, а потом два раза делает декремент, как последовательность "load-decrement-store".
User avatar
Think_Different
Уже с Приветом
Posts: 4864
Joined: 21 Oct 2016 14:32
Location: NYC

Re: Operators Precedence

Post by Think_Different »

depends on compiler
tau
Уже с Приветом
Posts: 510
Joined: 07 Dec 2001 10:01
Location: toronto

Re: Operators Precedence

Post by tau »

Более другой компилятор выдаёт "x = 3 z = 20".
В его защиту можно сказать, что он достаточно интеллигентен, чтоб выдать предупреждение типа "multiple unsequenced modifications to 'x'"
И правильно, в общем-то, нефиг в коде такие мины оставлять на радость грядущим поколениям.
User avatar
thinker
Уже с Приветом
Posts: 26853
Joined: 29 Aug 2000 09:01

Re: Operators Precedence

Post by thinker »

tau wrote: 22 Jun 2018 17:09 Зависит от компилятора.
Один из моих, к примеру, выдаёт "x = 3 z = 25".
То есть, он настолько умный, что сначала загружает x и умножает его сам на себя, а потом два раза делает декремент, как последовательность "load-decrement-store".
Да, я это и ожидал (z = 25). Теперь понятно, что так не надо писать. Нашел два правила на эту тему. Согласны с ними?

1) You can't apply the pre increment or the post increment more than once with an appearance of a variable.

2) Don’t use a variable that has a side effect applied to it more than once in a given statement. If applied more than once, the result may be undefined.
All rights reserved, all wrongs revenged.
tau
Уже с Приветом
Posts: 510
Joined: 07 Dec 2001 10:01
Location: toronto

Re: Operators Precedence

Post by tau »

thinker wrote: 22 Jun 2018 17:46
tau wrote: 22 Jun 2018 17:09 Зависит от компилятора.
Один из моих, к примеру, выдаёт "x = 3 z = 25".
То есть, он настолько умный, что сначала загружает x и умножает его сам на себя, а потом два раза делает декремент, как последовательность "load-decrement-store".
Да, я это и ожидал (z = 25). Теперь понятно, что так не надо писать. Нашел два правила на эту тему. Согласны с ними?

1) You can't apply the pre increment or the post increment more than once with an appearance of a variable.

2) Don’t use a variable that has a side effect applied to it more than once in a given statement. If applied more than once, the result may be undefined.
Согласен, если в первом пункте заменить can't на shouldn't. То есть, это пока явной ошибкой не является, пока что только на warning тянет. Хотя я бы стандарт поправил, чтоб такое вообще не компилировалось.

Вообще, со всеми эти современными out-of-order execution надо быть либо очень осторожным, либо уже на пенсии нафиг.
User avatar
thinker
Уже с Приветом
Posts: 26853
Joined: 29 Aug 2000 09:01

Re: Operators Precedence

Post by thinker »

tau wrote: 22 Jun 2018 17:19 Более другой компилятор выдаёт "x = 3 z = 20".
В его защиту можно сказать, что он достаточно интеллигентен, чтоб выдать предупреждение типа "multiple unsequenced modifications to 'x'"
Первоначально я попробовал с этим online компилятором:
https://ide.geeksforgeeks.org/index.php
И всё работает, но не так как ожидалось (z = 20).

И это кстати тоже компилируется: x = x--; // x is not changing :?

Потом попробовал с нашим рабочим компилятором (ARM Compiler) и он уже ругается и не хочет выдавать результат:
Warning[Pa079]: undefined behavior: variable "x" (declared at line 5) (or a value reached by some form of indirection through it) is modified more than once without an intervening sequence point in this statement main.c"
Вобщем теперь буду с ним всё проверять. Спасибо всем кто ответил.
All rights reserved, all wrongs revenged.
User avatar
AndreyT
Уже с Приветом
Posts: 3009
Joined: 14 Apr 2004 01:11
Location: SFBA (было: Минск, Беларусь)

Re: Operators Precedence

Post by AndreyT »

thinker wrote: 22 Jun 2018 15:55 Кто-нибудь может объяснить почему результат: x = 3, z = 20 ?
х = 3 понимаю, z = 20 нет.
Поведение не определено. Никакого осмысленного результата тут нет и быть не может. Утверждать, что результат якобы "зависит от компилятора" - профанация. "Поведение не определено" означает, что оно может меняться непредсказуемо и в рамках одного компилятора.

Отдельно стоит заметить, что языки С и С++ в наши дни очень сильно (!) отличаются с точки зрения определения поведения в таких случаях. То есть в общем случае вопрос бессмыслен без указания языка: С или С++. Но в данном конкретном случае `x-- * x--` поведение не определено в обоих.
thinker wrote: 22 Jun 2018 19:21 И это кстати тоже компилируется: x = x--; // x is not changing :?
А вот тут уже вылазит разница между С и С++. В С - поведение не определено. В С++, начиная с С++17, поведение определено однозначно: 'x' не меняется.

Поэтому, еще раз: все разглагольствования выше совершенно бессмыслены без указания конкретного языка.
Last edited by AndreyT on 23 Jun 2018 04:25, edited 5 times in total.
Best regards,
Андрей
User avatar
thinker
Уже с Приветом
Posts: 26853
Joined: 29 Aug 2000 09:01

Re: Operators Precedence

Post by thinker »

AndreyT wrote: 23 Jun 2018 00:23 А вот тут уже вылазит разница между С и С++. В С - поведение не определено. В С++ поведение определено: 'x' не меняется.

Поэтому, еще раз: все разглагольствования выше совершенно бессмыслены без указания конкретного языка.
У меня C и компилятор на это, x = x--; тоже ругается и не выдает результат.
All rights reserved, all wrongs revenged.
User avatar
AndreyT
Уже с Приветом
Posts: 3009
Joined: 14 Apr 2004 01:11
Location: SFBA (было: Минск, Беларусь)

Re: Operators Precedence

Post by AndreyT »

thinker wrote: 23 Jun 2018 00:29 У меня C и компилятор на это, x = x--; тоже ругается и не выдает результат.
Ну так именно С и может/должен ругаться - в С поведение не определено. Вполне может быть, что ваш С компилятор в этом случае гарантирует, что 'x' не меняется, т.е. ведет себя предсказуемо, но с точки зрения языка С это не более чем одно из возможных проявлений неопределенного поведения.

В С++ на уровне языка гарантируется, что 'x' просто не поменяется. (GCC в режиме С++ все равно будет нервничать и предупреждать при наличии `-Wsequence-point`, но это просто их недоделка.)

P.S. "Operator precedence", кстати, никакого отношения к этому не имеет. В С и С++ "operator precedence" не диктует ни порядка выполнения, ни (тем более) моментов материализации побочных эффектов. Это вам не Java.
Best regards,
Андрей

Return to “Вопросы и новости IT”