9

In C or C++ I know that there is something called

undefined behaviour

In expression evaluation when some of the the expressions have side-effects. let's say I want to calculate the following:

c = 10
f() + g() + c

but at some point g makes c = 5.(c is a glob variable)

What would be the behavior in python? Would it be undefined as C?

borisbn
  • 4,988
  • 25
  • 42
  • 1
    yes, possible if `c` is a global variable. but in python operators are evaluated from left to right. – Jean-François Fabre Mar 01 '18 at 11:10
  • 4
    Do you mean "undefined behavior" not "unexpected behavior"? "Undefined behavior" is, indeed, generally unexpected. :) Unexpected behavior, though, may very well be well-defined behavior in the language,but unexpected because the programmer isn't aware of the rules of execution in that case. – lurker Mar 01 '18 at 11:30
  • 3
    Youv'e used two terms "unexpected" and "unspecified" - neither of which are used in the C or C++ standards. There are only "defined", "undefined" and "implementation defined" behaviour. Using the right terms is important because other terms are, err... _undefined_ ;-) – Clifford Mar 01 '18 at 11:38
  • Corrected the terms. :) – Mark R. Chandar Mar 01 '18 at 11:48
  • Yes c is a global variable. I know it is undefined in C language but I want to know more about python. So in python it is always left to right which means the interpreter is going to take c as 5 instead of 10 while calculating the expression – Mark R. Chandar Mar 01 '18 at 11:50
  • 2
    @MarkR.Chandar But the code does _not_ invoke undefined behavior. Undefined and unspecified are different formal terms with certain meanings, "unexpected" is not a formal term. – Lundin Mar 01 '18 at 11:58
  • If you knew that g() affected c, you'd be wise not to write that expression - even if it is well defined. It is ambiguous what the programmer intended/expected even if the interpreter is predictable . C and C++ have international standards, and multiple implementations on varies targets and architectures and are of course _systems-level_ _compiled_ languages. Python is a single _project_ and is an _interpreted_ _scripting_ language - so isolated from architecture dependencies. If the result is not the same on all platforms, that would be a bug rather than undefined behaviour. – Clifford Mar 01 '18 at 12:37
  • I stand corrected by @Lundin - there _is_ also "unspecified". If you just call it all UB, you cannot be wrong! – Clifford Mar 01 '18 at 12:41
  • @Armali No I am not, since there is a sequence point after the evaluation of a function's parameters, one for every semicolon inside the function, and yet another before the function returns. Off you go to read Annex C of the standard. – Lundin Mar 01 '18 at 15:02

3 Answers3

10

From 6.15 of documentation

Python evaluates expressions from left to right. Notice that while evaluating an assignment, the right-hand side is evaluated before the left-hand side.

In the following lines, expressions will be evaluated in the arithmetic order of their suffixes:

expr1, expr2, expr3, expr4
(expr1, expr2, expr3, expr4)
{expr1: expr2, expr3: expr4}
expr1 + expr2 * (expr3 - expr4)   <----- This is of importance to us.
expr1(expr2, expr3, *expr4, **expr5)
expr3, expr4 = expr1, expr2

So here the functions will be called in order from left to right. So any of the changes you will see will be due to the functions called from left to right.

And yes in function calls are expressions.

Community
  • 1
  • 1
user2736738
  • 30,591
  • 5
  • 42
  • 56
5

C code such as this:

#include <stdio.h>

int c;

int f (void)
{
  return 1;
}

int g (void)
{
  return ++c;
}

int main()
{
  c = 3;

  printf("%d", f() + g() + c);

  return 0;
}

does not invoke undefined behavior. It does however invoke unspecified behavior. These are different, formal terms: Undefined, unspecified and implementation-defined behavior

Note first that f() + g() + c is grouped as (f() + g()) + c but that tells you nothing about the order in which the terms themselves are actually evaluated.

The result of this code can either be 1 + (3+1) + 3 = 8 or 1 + (3+1) + 4 = 9, depending on if the operand g() is evaluated before or after the operand c. The order of evaluation of operands of the + operator is unspecified, so we can't know which operand that gets evaluated first, nor should we write code that relies on a certain order.

The code will only ever give either of the two mentioned results, it will not do anything completely crazy, like crashing or giving garbage results, which code containing undefined behavior could do. An example of undefined behavior would be c++ + c++.

The difference between the examples is where the side effects take place. See Undefined behavior and sequence points

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • This is a nice answer; why the lack of attention? (I didn't have you down as a 2 space indenter ;-)) – Bathsheba Mar 01 '18 at 12:46
  • I've gone over my pay grade and added a paragraph on grouping. Do please roll back if you don't like it. – Bathsheba Mar 01 '18 at 12:49
  • @EricPostpischil Indeed it would be better if Lundin had mentioned that Python does not detach grouping from evaluation. – Bathsheba Mar 01 '18 at 14:10
  • How would `c++ + c++` result in a crash or garbage results? If `c == n` prior to execution, then wouldn't it evaluate to either `n + n` or `n + n + 1`, while setting `c` to `n + 2`? – flarn2006 Oct 10 '19 at 21:24
  • @flarn2006 Undefined behavior is behavior which is not defined. The compiler is for example free to not generate any machine code at all for that line. https://stackoverflow.com/questions/949433/why-are-these-constructs-using-pre-and-post-increment-undefined-behavior – Lundin Oct 11 '19 at 06:41
  • @Lundin: Oh really? Does the standard explicitly list it as undefined? Because the binary `+` and post-increment `++` operator are both defined, so I'd think there'd at least be some constraints set by the standard, even if it doesn't lay out exactly what it should do. I'm not saying I think you're wrong; I'm just surprised. – flarn2006 Oct 11 '19 at 13:42
1

If c is a global variable, and g() is making the same c to be the value of 5, meaning that this is unspecified behaviour.

Note, Python interpreters evaluate expressions from left to right, meaning that the c would be 5 when it's added to f() + g().

Adi219
  • 4,712
  • 2
  • 20
  • 43