1

When the evaluation of l-value precedes the evaluation of r-value and the assignment also returns a value, which of the following is evaluated first?

int i = 2;
int x[] = {1, 2, 3};
int y[] = {4, 5, 6};
int z[] = {7, 8, 9};

x[--i] = y[++i] = z[i++]; // Out of bound exception or not?

NOTE: generic C-like language with l-value evaluation coming first. From my textbook:

In some languages, for example C, assignment is considered to be an operator whose evaluation, in addition to producing a side effect, also returns the r-value thus computed. Thus, if we write in C:

x = 2;

the evaluation of such a command, in addition to assigning the value 2 to x, returns the value 2. Therefore, in C, we can also write:

y = x = 2;

which should be interpreted as:

(y = (x = 2));
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
gremo
  • 47,186
  • 75
  • 257
  • 421
  • 4
    Undefined behaviour, I think... – dreamlax Feb 01 '11 at 21:43
  • Even if it's not UB, it's pretty terrible code. –  Feb 01 '11 at 21:44
  • 2
    Also, there's no such thing as an "out of bound" exception in C. And, your declarations are syntactically incorrect. – dreamlax Feb 01 '11 at 21:44
  • @dreamlax: i don't thinks so, since l-value comes first that expression is valid. @delnan: homework, I would never write such a thing. – gremo Feb 01 '11 at 21:45
  • Interesting. I never fully grasped this "sequence point" thing, this code may well be defined after all. – Alexandre C. Feb 01 '11 at 21:48
  • 4
    Surely you see how pointless it is to ask for a language rule in a "pseudo-language". – GManNickG Feb 01 '11 at 21:48
  • The excerpt from your text book is well-defined because you are not modifying any variables more than once within a sequence point. – dreamlax Feb 01 '11 at 22:01
  • But based on that excerpt, it seems that you can first evaluate the y (l-value), x[--i] in my example. Then you should evaluate the x (y[++i]) and last consider z[i++]. The inner assignment value then becomes the r-value of the x array. I can't see any UB in this, because there is precise sequence of evaluation... – gremo Feb 01 '11 at 22:05
  • 2
    I compiled your code on two separate compilers; with GCC (it warned that the operations on `i` may be undefined), `i` was equal to 3 after the all of the assignments. With Clang, `i` was equal to 9 after all of the assignments. Gremo, you need to understand that sequence of evaluation and sequence points are two different concepts. When you modify a variable more than once within one sequence point (in this case, `i`), the behaviour is undefined. – dreamlax Feb 01 '11 at 22:13
  • @dreamlax: Got it. Got the idea, but I can't figure out why "Clag" gives you i = 9. Apart from any expression re-ordering / optimization made by the compiler, we have just 3 operations on i; even not considering the order, at the end is just: add 1, add 1, subtract 1. Result should be always 3. What I'm missing? – gremo Feb 01 '11 at 22:22
  • 1
    @Gremo: That's the thing about undefined behaviour :) Any value is legitimate, because the standard makes no guarantees. I agree though that 9 is an odd value, perhaps it came from inside one of the arrays? – dreamlax Feb 01 '11 at 22:25
  • @dreamlax: dunno, I'm just more confused now that before. I will talk with my "languages and compilers" professor tomorrow, asking about this undefined behavior. Thank you for answering and helping. – gremo Feb 01 '11 at 22:29
  • @Gremo: Sequence Points is usually advanced topic in C. Sometimes it is never even discussed. If you want to understand a little more, you can download [this PDF](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf) (the C language specification), and have a look at §5.1.2.3 and at Annex C. These two sections define what a sequence point actually is, and also summarise what parts of C are sequence points. – dreamlax Feb 01 '11 at 22:36
  • 3
    Subject is misleading, and this question is a duplicate of the weekly sequence point UB nonsense. – R.. GitHub STOP HELPING ICE Feb 01 '11 at 23:09
  • possible duplicate of [How do we explain the result of the expression (++x)+(++x)+(++x)?](http://stackoverflow.com/questions/1525187/how-do-we-explain-the-result-of-the-expression-xxx) – Jonathan Leffler Dec 25 '11 at 17:21

3 Answers3

6

I'm quite certain that the behaviour in this case is undefined, because you are modifying and reading the value of the variable i multiple times between consecutive sequence points.

Also, in C, arrays are declared by placing the [] after the variable name, not after the type:

int x[] = {1, 2, 3};

Edit:

Remove the arrays from your example, because they are [for the most part] irrelevant. Consider now the following code:

int main(void)
{
    int i = 2;
    int x = --i + ++i + i++;
    return x;
}

This code demonstrates the operations that are performed on the variable i in your original code but without the arrays. You can see more clearly that the variable i is being modified more than once in this statement. When you rely on the state of a variable that is modified between consecutive sequence points, the behaviour is undefined. Different compilers will (and do, GCC returns 6, Clang returns 5) give different results, and the same compiler can give different results with different optimization options, or for no apparent reason at all.

If this statement has no defined behaviour because i is modified several times between comsecutive sequence points, then the same can be said for your original code. The assignment operator does not introduce a new sequence point.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
dreamlax
  • 93,976
  • 29
  • 161
  • 209
2

General

In C, the order of any operation between two sequence points should not be dependent on. I do not remember the exact wording from the standard, but it is for this reason

i = i++;

is undefined behaviour. The standard defines a list of things that makes up sequence points, from memory this is

  1. the semicolon after a statement
  2. the comma operator
  3. evaluation of all function arguments before the call to the function
  4. the && and || operand

Looking up the page on wikipedia, the lists is more complete and describes more in detail. Sequence points is an extremely important concept in C and if you do not already know what it means, do learn it immediately.

Specific

No matter how well defined the order of evaluation and assignment of the x, y and z variables are, for

x[--i] = y[++i] = z[i++];

this statement cannot be anything but undefined behaviour because of the i--, i++ and i++. On the other hand

x[i] = y[i] = z[i];

is well defined, but I am not sure what the status for the order of evaluation for this. If this is important however I would rather prefer this to be split into two statements along with a comment "It is important that ... is assigned/initialized before ... because ...".

hlovdal
  • 26,565
  • 10
  • 94
  • 165
  • The associativity of the assignment operator is right to left, so the order of evaluation in your last example will be `(x[i] = (y[i] = z[i]));` – Fred Larson Feb 01 '11 at 22:33
-3

i think its the same as

x[3] = y[4] = z[2];
i = 3;
Yasir
  • 27
  • 1
  • 4
    This is one possible outcome, but the C standard does not guarantee this; the result could be thunderstorms and 35°C. It's undefined. – dreamlax Feb 01 '11 at 21:52