Using comma operator in c - c

I have read that comma operator is used to assign expression, and the right expression is supplied to lvalue.
But why does this program assign left expression to lvalue when not using parenthesis? I am using turbo c compiler.
int b=2;
int a;
a=(b+2,b*5); // prints 10 as expected
a=b+2,b*5; // prints 4 when not using parenthesis
Also the following works:
int a =(b+2,b*5);
But this generates an error:
int a =b+2,b*5; // Error
I can't understand why.

Because precedence of , operator is lower than of = one, this...
a=b+2,b*5;
... will actually be evaluated as...
a = b + 2;
b * 5;
With int i = b + 2, b * 5; is a bit different, because comma has different meaning in declaration statements, separating different declarations from each other. Consider this:
int a = 3, b = 4;
You still have comma here, but now it separates two variable assignment-on-declarations. And that's how the compiler attempts to treat that line from your example - but fails to get any meaning from b * 5 line (it's neither assignment nor declaration).
Now, int a = (b + 2, b * 5) is different: you assign a value of b + 2, b * 5 expression to a variable a of type int. The first sub-expression is discarded, leaving you just with b * 5.

Related

What is this C behavior called

I'm learning C as Javascript developer and a common mistake that I make is when I'm supposed to define multiple variables in C like this
int a, b, c;
a = b = c = 0;
I accidentally do it the Javascript way
a,b,c = 0;
I'm wondering what the above is called and when I should define variables like this.
I'm wondering what the above is called....
Two things about this statement
a,b,c = 0;
First, this is same as
a;
b;
c = 0;
The expression a; and b; result is unused.
The compiler must be throwing warning messages on this statement. When I compiled with clang compiler, I am getting following warnings:
p.c:6:2: warning: expression result unused [-Wunused-value]
a, b, c = 9;
^
p.c:6:5: warning: expression result unused [-Wunused-value]
a, b, c = 9;
^
and Second, the , in the statement is , (comma) operator.
Precisely stated, the meaning of the comma operator in the general expression
e1 , e2
is evaluate the subexpression e1 and discards the result , then evaluate e2; the value of the expression is the value of e2.
So, the value of expression a,b,c = 0 is value of c = 0. The variable a and b will remain uninitialised.
May you can try this and check the variable values after this statement:
a = 99, b = 5, c = 0;
Since you are learning C, let me tell you one more thing - The , (comma) act as separator in function calls and definitions, variable declarations, enum declarations, and similar constructs. To begin with, check this.
and when I should define variables like this.
The statement a,b,c = 0; is not definition of variable a, b and c. You have defined the variable a, b and c here
int a, b, c;
Note that in this statement, the , is act as separator.
Its use is completely depends on you as long as you know very well about it. One of the very common use of , (comma) operator is in for loop, where it can be used to initialise multiple variables and/or increment/decrement loop counter variable and other variables etc., for example :
for (i = 0, j = some_num; i < some_num; ++i, --j) ....
Divide it up by the operators:
int a, b;
a = b = 10;
^ ^^^^^^
| Right operand
Left operand
Here, first it calculates b = 10 to assign to a. b = 10 "returns" the new value of b which is 10, and that is assigned to a. It works similarly with more variables:
int a, b, c;
a = b = c = 10;
^^^^^^-Done first
^^^^^-Done second
^^^^^-Done last
a, b, c = 10 does not work the same way. First of all, you have to declare them first before assigning. Also, this uses the , operator which has a lower precedence than =, so the line is equivalent to a; b; c = 10;. As you can see, nothing really happens to a or b and only c is set to 10.
The comma used as an operator is called the comma operator.
For details, read a C standard, like n1570 (§6.5.17) or later. The semantics is defined as:
The left operand of a comma operator is evaluated as a void expression; there is a sequence point between its evaluation and that of the right operand. Then the right operand is evaluated; the result has its type and value
Of course, inside function calls like printf("x=%d y=%d\n", x, y) the comma is separating arguments. Inside macro invocations and definitions also. In that case, it is the comma punctuator (see n1570 §6.5.2, 6.7, 6.7.2.1, 6.7.2.2,6.7.2.3, 6.7.9)
If you compile with GCC, invoke it as gcc -Wall -Wextra -g. You could get useful warnings.
Consider, if so allowed, to use the Clang static analyzer (or other tools like Frama-C or Bismon; you may contact me in 2021 by email to basile.starynkevitch#cea.fr)
Take inspiration from the source code of existing free software programs like GNU make or GNU bash. They rarely use the comma operator.
In c language you can define the variable using one line
int a,b,c;
This is same as
int a;
int b;
int c;
You can define and initialize this one like this
int a,b,c;
a=b=c=10;
if you write
int a,b,c;
a,b,c=10;
it will initialize c as 10 but others will not inilizes as 10;
a and b will be defined but not initialized it will return garbage value.

a=3,2,1; gives error in gcc

I tried the following code in gcc:
#include<stdio.h>
int main()
{
int a=3,2,1;//////////////////////ERROR!//////////////////////////
printf("%d", a);
return 0;
}
I expected it to compile successfully as:
a series of integer expressions seperated by commas will be evaluated from left to right and the value of the right-most expression becomes the value of the total comma separated expression.
Then, the value of the integer variable a should have been 1 right? Or is it 3?
And why am I getting this error when I try to execute this program?
error: expected identifier or '(' before numeric constant
That's parsed as a three-part variable declaration, with two invalid variables.
You need to wrap the entire initializer in parentheses so that it's parsed as a single expression:
int a=(3,2,1);
If you separate the initialization from the declaration, you may get what you expected:
int a;
a = 3, 2, 1; // a == 3, see note bellow
or
int a;
a = (3, 2, 1); // a == 1, the rightmost operand of 3, 2, 1
as your original command is syntactically incorrect (it is the declaration so it expected other variables to declare instead of numbers 2 and 1)
Note: All side effects from the evaluation of the left-operand are completed before beginning the evaluation of the right operand.
So
a = 3, 2, 1
which are 3 comma operators a = 3, 2 and 1 are evaluated from left to right, so the first evaluation is
a = 3, 2
which result 2 (right-operand) (which is by the way not assigned to any variable, as the value of the left-operand a = 3 is simply 3), but before giving this result it is completed the side effect a = 3 of the left-operand, i. e. assigning 3 to variable a. (Thank AnT for his observation.)

Why isn't the compound assignment taken into account when displaying the latter 'tot'?

#include <stdio.h>
main() {
int pro;
int dot;
int tot;
char prelude[] = "\nNow we shall do some simple mathematics\n\n";
printf("%s", prelude);
pro = 3;
dot = 5;
tot = pro + dot;
printf("%d", tot);
dot += 23;
printf("\n%d\n", tot);
return 0;
}
Because C does not offer automatic data binding. When you use the assignment operator (or Addition assignment in your case), you are assigning the VALUE of the statement on the right hand side of the expression.
variable = statement means that statement will be calculated to some value, and this value will be assigned to variable according to variable's data type.
This means that you are assigning a value, not an actual statement to that variable.
To explain it better:
tot = pro + dot;
does the following:
I need to assign something that I must calculate to the variable tot.
Something is a statement, pro + dot.
This statement is an addition, an operation that takes two operands.
Operand 1 is pro, it evaluates to 3. (means that C will replace
pro with 3 in that statement)
Operand 2 is dot, it evaluates to 5.
All of the operands are evaluated.
The statement is: 3 + 5;
This evaluates to 8, an integer.
The expression has become tot = 8;
Assign the value 8 to tot. This means, go to the memory address
of the variable represented by tot, and write the integer 8 (in
accordance with the C standard/machine architecture).
If you do
dot += 23;
C understands this:
dot += 23; // can be translated to `dot = dot + 23;'
Like before:
dot means 8, 23 means 23.
statement: 8 + 23
The statement evaluates to 31. dot = 31;, meaning write the
integer 31 to the memory of dot.
Now tot , is unaffected by that. Why? Because tot is a space in your memory, that holds the value 8. It doesn't know that 8 was created by adding 2 other variables. It's just 8. So changing the other variables, will not affect this one.
If you do dot += 23;, you are changing the memory of the variable dot, not that of tot.
What you were expecting, is called data binding, and is a much higher level feature than what C offers.

Are "arithmetic expressions" separated by commas allowed in C or we need separate statements for each?

In C, is the following statement
a+=3,b=c*2,d=a+b;
equivalent to the following block of statements:
a+=3;
b=c*2;
d=a+b;
I am sure you got my point. Can we safely use multiple mathematical expressions separated by commas in the same statement in C? And in what cases this can pose problems?
It might be easier if you think of the comma-expression list you present like this:
((a += 3, b = c * 2), d = a + b)
First the innermost comma-expression is evaluated:
a += 3, b = c * 2
That expression will be evaluated in two steps:
a += 3
b = c * 2
The result of a += 3 will be thrown away by the compiler, but the assignment still happens, it's just that the returned result is thrown away. The result of the first comma expression is b (which will be c * 2 (whatever that is)).
The result of the first comma expression is then on the left-hand side of the next comma expression:
b = c * 2, d = a + b
Which will then be sequenced as
b = c * 2
d = a + b
The result of the expression b = c * 2 is thrown away (but as it is still evaluated the assignment still happens), and the result of the complete expression is d (which is a + b).
The result of the whole expression will be d.
They are the same.
In C, the comma operator evaluates its left hand side, ignores the return value (for example the return of x = y is the new value), evaluates the right hand side and returns its result (if any). The use of the comma operator is to evaluate and get the side effects of what's on the left hand without using (e.g. discarding) its value.

why lvalue required as increment operand error? [duplicate]

This question already has answers here:
lvalue required as increment operand error
(4 answers)
Closed 8 years ago.
Why lvalue required as increment operand Error In a=b+(++c++); ?
Just Wanted to assign 'b+(c+1)' to 'a' and Increment 'C' by 2 at the same time.
I'M A Beginner Just Wanted A Clarification About What "LVALUE ERROR" Actually Is?
main()
{
int a=1,b=5,c=3;
a=b+(++c++);
printf("a=%d b= %d c= %d \n",a,b,c);
}
Postfix increment binds tighter than prefix increment so what you would want would be something like:
a = b + (++c)++;
This is not legal C, though, as the the result of prefix increment (like the result of postfix increment in your example) is not an lvalue. This means that it's just a value; it doesn't refer to a particular object like 'c' any more so trying to change it makes no sense. It would have no visible effect as no object would be updated.
Personally I think that doing it in two statements is clearer in any case.
a = b + c + 1;
c += 2;
LVALUE means, that there isn't a variable the operation is supposed to be performed on.
C files are basically nothing but text files, which require a particular formatting, so the compiler can understand it.
Writing something like ++Variable++ is complete nonsense for the compiler.
You can basically imagine ++c as:
Var += 1;
return Var;
while c++ is:
int Buf = Var;
Var += 1;
return Buf;
To 'repair' your code:
void main() {
int a=1,b=5,c=3;
a = b + (++c); //Equals 5 + 4
printf("a=%d b= %d c= %d \n",a,b, ++c); //a = 9, b = 5, c = 5
}
This way, you'll get the result you wanted, without the compiler complaining.
Please remember, that when using ++c or c++ in a combined operation, the order DOES matter.
When using ++c, the higher value will be used in the operation, when using c++, it will operate with the old value.
That means:
int a, c = 5;
a = 5 + ++c; //a = 11
while
int a, c = 5;
a = 5 + c++; //a = 10
Because in the latter case, c will only be '6' AFTER it is added to 5 and stored in a.

Resources