1

I read many questions here but couldn't find my answer, considering following statements:

int x;
x = 1, 2, 3;

this gives x value of 1 however as there are other values separated by , why the rest is discarded? shouldn't it be 3? or is it because of precedency of = over ,?

Then if I write

int x = 1, 2, 3;

now it doesn't compile. what's the real difference between the two?

user174174
  • 119
  • 1
  • 5
  • You can verify your assumption regarding operator precedence by simply putting `1,2,3` in brackets: `(1,2,3)` – Gerhardh Aug 17 '22 at 09:47
  • If something does not compiler you should show the exact error message. – Gerhardh Aug 17 '22 at 09:47
  • `x=1,` is a syntactically correct expression. `2,` is another, `3;` is another... Now, does the difference begin to make sense? – Fe2O3 Aug 17 '22 at 09:53
  • This `printf("x=%d\n", x), 42;` perhaps shows why there is a difference between `x = 1, 2, 3;` and `x = (1, 2, 3);`. – Weather Vane Aug 17 '22 at 09:55
  • 1
    First one is a sequence of three sub-expressions executed one after another with the last one being the final result of the combined expression. You might want to play around a bit: `x = 1, y = 2, z = 3` or `z = (x = 1, y = 2)` or `z = (x = 1, 2)`. – Aconcagua Aug 17 '22 at 09:56

2 Answers2

2

You already found out that = has higher precedence. Therefore that first code is similar to

(x = 1),2, 3;

That means you have an assignment and you have 2 values combined by comma operator.

The assignment is evaluated to 1 (besides actually assigning a value to x) and you get an expression like this: 1,2,3; which is evaluated but ignored.

In your second snippet things are different.

int x =1, 2, 3;

Again the precedence is same.

If you add brackets int x = (1,2,3); you will get value 3 as you expected.

Without the brackets, the compiler expects the name of the next variable that you want to define here. 2 and 3 are no valid identifiers to define variables and therefore the compiler complains.

Gerhardh
  • 11,688
  • 4
  • 17
  • 39
1

x = 1, 2, 3;

Due to precedence, this is interpreted as (x = 1), 2, 3;.

int x = 1, 2, 3;

In an expression statement such as x = 1, 2, 3;, you can use any expression. However, in a declaration, an initializer can only be an assignment-expression (or a list of initializers inside { and }).

The way the formal C grammar is written, the top-level operator of an expression can be any of the C operators, but the top-level operator of an assignment-expression can be any of the C operators except ,. Therefore, if a , is seen when parsing the top level of an initializer, it cannot be part of the initializer, so it ends the initializer. (A , can appears inside parentheses in an initializer.)

Here are some details about how this works. The formal grammar says:

  • An expression is either expression , assignment-expression or is an assignment-expression.
  • An assignment-expression is either unary-expression assignment-operator assignment-expression or is a conditional-expression.
  • A conditional-expression is either logical-OR-expression ? expression : conditional-expression or is a logical-OR-expression.
  • This chain continues through all the operators in C.

So, when a C compiler is looking for an expression, it notionally goes through each of these choices, accepting either a comma operator or an assignment operator or a conditional operator, and so on. When it is looking for an assignment-expression (in a declaration), it starts with the second choice, an assignment operator, notionally skipping over the comma as a possibility.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • TYSM for much broader explanation, can you please give a short example for each list items you kindly mentioned? That would be much helpful. – user174174 Aug 18 '22 at 00:23