51

Why does an expression i = 2 return 2? What is the rule this is based on?

printf("%d\n", i = 2 ); /* prints 2 */

I am in C domain after spending long time in Java/C#. Forgive my ignorance.

Nemo
  • 4,601
  • 11
  • 43
  • 46

5 Answers5

63

It evaluates to 2 because that's how the standard defines it. From C11 Standard, section 6.5.16:

An assignment expression has the value of the left operand after the assignment

It's to allow things like this:

a = b = c;

(although there's some debate as to whether code like that is a good thing or not.)

Incidentally, this behaviour is replicated in Java (and I would bet that it's the same in C# too).

DevSolar
  • 67,862
  • 21
  • 134
  • 209
Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • 1
    I generally am ok with this when `a` and `b` are really the same thing as opposed to just happening to be the same value. I use the same reasoning to decide between `int presentValue, previousValue;` vs. `int myAge; int myHeight;`. Present and previous values should never have different types while I may choose to use a `float` for my height instead of an `int`. Just another layer of intent that can be either captured. – altendky Aug 28 '15 at 14:09
  • 3
    Updated link by @SurajJain to C11. What this construct *also* allows is the (much more useful) `if ( ( ptr = func() ) != NULL )`... – DevSolar Feb 20 '17 at 09:01
24

The rule is to return the right-hand operand of = converted to the type of the variable which is assigned to.

int a;
float b;
a = b = 4.5; // 4.5 is a double, it gets converted to float and stored into b 
// this returns a float which is converted to an int and stored in a
// the whole expression returns an int
M.M
  • 138,810
  • 21
  • 208
  • 365
foxx1337
  • 1,859
  • 3
  • 19
  • 23
  • 1
    Could you provide a reference? Oli Charlesworth says that in C99 it is the value of the left operand, so this would be a difference with C++? – Benoit Mar 01 '12 at 10:35
  • So, this is in contradiction with your answer (rvalue => lvalue, right side => left side). – Benoit Mar 01 '12 at 10:39
  • 1
    There's no real contradiction. "rvalue converted to the variable type" is exactly what the variable (the lvalue) will be after the assignment. Two ways of saying the same. The "lvalue after assignment" rule also applies as-is for `+=` etc. – ugoren Mar 01 '12 at 11:10
  • 2
    IIRC there is indeed a difference here - `b = 4.5` evaluates to a value `4.5` in C, but in C++ it's an lvalue referring to `b`. A difficult lvalue to actually use on the LHS of an assignment, since for example `(a = b) = 1` is UB anyway due to the lack of a sequence point between the two modifications of `a`. But I think in C++ you can take the address `&(a = 1)` and it's the address of `a`, and in C you can't. Someone correct me if I'm wrong. – Steve Jessop Mar 01 '12 at 11:18
4

It consider the expression firstly then print the leftmost variable.

example:

int x,y=10,z=5;
printf("%d\n", x=y+z );  // firstly it calculates value of (y+z) secondly puts it in x thirdly prints x

Note:

x++ is postfix and ++x is prefix so:

int x=4 , y=8 ;
printf("%d\n", x++ );  // prints 4
printf("%d\n", x );    // prints 5
printf("%d\n", ++y );    // prints 9
Ahmed Salah
  • 851
  • 2
  • 10
  • 29
  • *you know calculations are done from right to left.* not really. Calculations can be done in any order, including assignments. Argument values are computed before the function is called, but that's about the only assumption you can make. The important thing to understand is the concept of sequence point. – chqrlie Feb 20 '17 at 10:03
  • You are right man! but I mean the simple ones like x=y+z, I edited the answer, Thank you. – Ahmed Salah Feb 20 '17 at 10:20
3
  1. Assign the value 2 to i
  2. Evaluate the i variable and display it
animuson
  • 53,861
  • 28
  • 137
  • 147
Sandro Munda
  • 39,921
  • 24
  • 98
  • 123
2

In C (almost) all expressions have 2 things
1) a value
2) a side effect

The value of the expression

2

is 2; its side effect is "none";

The value of the expression

i = 2

is 2; its side effect is "changing the value in the object named i to 2";

pmg
  • 106,608
  • 13
  • 126
  • 198
  • Fully *50%* of possible C expressions are `(void)` followed by another expression (for certain values of "proportion of an infinite set"). Do they count has having a value, or not? ;-) – Steve Jessop Mar 01 '12 at 11:21
  • No, `(void)` expressions have no value. Eg: the expression `free(pointer)` has no value. – pmg Mar 01 '12 at 11:34
  • @pmg: `free(pointer)` indeed has no value, but it is not worthless, although many programmers consider it not worth the effort. – chqrlie Feb 20 '17 at 09:59