assignment operators and c - c

#include <stdio.h>
int main()
{
int i,j;
i=j=(22,23,24);
printf("i:%d",i);
printf("\nj:%d",j);
}
this is giving output of both i,j as 24.
#include <stdio.h>
int main()
{
int i,j;
i=j=22,23,24;
printf("i:%d",i);
printf("\nj:%d",j);
}
and this gives both i,j as 22.
Can someone explain the terminlology behind.
TIA

An assignment operator = has higher precedence than a comma operator ,.
C Operator Precedence - cppreference.com
In this statement
i=j=(22,23,24);
(22,23,24) is firstly calculated. The 22 and 23 are ignored by the comma operator and it is evaluated to 24. Then, the result 24 is assigned to j, and the value is also assigned to i.
On the other hand, in this statement
i=j=22,23,24;
i=j=22 is firstly calculated. This assigns 22 to j, then assign the value to i. After that, the evaluation result of assignment operator 22, and an integer literal 23 are ignored by the comma operator. Finally the expression is evaluated to the value 24, which is also ignored.

A comma separated list of constant expressions does not make much sense. The main purpose of comma operator is to separate assignments - a transparent and conscious side-effect.
With parentheses and two more assignments it groups as:
i = j = (22,x=23,y=24);
Since an expression in parens (E) is a primary expression, this can be hierarchically seen as
i = j = E;
This E consists of three comma separated (sub-)expressions where the last one counts. This is assignment y=24 with result/evaluation 24.
The 22 is thrown away, but x=23 has the obvious side effect.
Normally E would be something like 2*n+1 that does not need parens. Until up to the i = j > 22 ? 23 : 24 (where it gets a bit confusing).
The second one groups:
i=j=22, x=23, y=24;
This starts to make sense now. It is just three assigments on one line. 23 and 24 are not "lost".
The assigment expression i=j=22 itself has one level of recursion; it works right-to-left, which is only natural.
But the examples are more about combining separating comma operators , and grouping parentheses ( ).

Related

How does this return statement with multiple values (variables) works? [duplicate]

This question already has answers here:
What does the comma operator , do?
(8 answers)
Closed 7 years ago.
I am trying to get some understanding about how pass by value & return are happening in C functions. I cam across a piece of code as follows:
#include <stdio.h>
int fun(int ii, int jj)
{
int kk, ll;
kk = ii + jj;
ll = ii * jj;
return (kk,ll);
}
int main()
{
int i=4, j=5, k, l;
k = fun(i, j);
l = fun(i, j);
printf("%d %d\n", k, l);
return 0;
}
Now apparently I am not getting any errors when I am trying to return 2 values through fun().
Also, the value that is returned by fun() is ll i.e 20 (=4*5) and not kk. Further, If I rewrite the return statement as :
return (ll,kk);
the value returned is that of kk ie. 9 (=4+5).
Query: Why this is so?
In your code, in the return statement
return (kk,ll);
you're using the comma operator. By the property of the comma operator, you're not returning two values, rather you're returning the second operand of the comma operator only.
To elaborate, let's check the property of the comma operator, directly quoting the standard, C11, chapter §6.5.17, (emphasis mine)
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.
So, essentially, a return statement like
return (kk,ll);
is same as
return ll;
Hope you can figure out the other case.
That said, the recommended signature for main() is int main(int argc, char*argv[]) or , at least, int main(void).
What do you expect when returning an int? C does not support tuples.
You are using the comma-operator. (ll, kk) is a single expression with the inner expressions (seperated by , - thus the name) being evaluated left to right. All but the rightmost (you can have more than two sub-expressions) results are discarded and the rightmost result is the result of the whole expression. Actually the parenthesis are unnecessary and do not change anything.
You are using the comma operator.
The comma operator (represented by the token ,) is a binary operator that evaluates its first operand and discards the result, and then evaluates the second operand and returns this value (and type).

understanding printf() in C [duplicate]

Please explain the output of this program:
int main()
{
int a,b,c,d;
a=10;
b=20;
c=a,b;
d=(a,b);
printf("\nC= %d",c);
printf("\nD= %d",d);
}
The output which I am getting is:
C= 10
D= 20
My doubt is what does the "," operator do here?
I compiled and ran the program using Code Blocks.
The , operator evaluates a series of expressions and returns the value of the last.
c=a,b is the same as (c=a),b. That is why c is 10
c=(a,b) will assign the result of a,b, which is 20, to c.
As Mike points out in the comments, assignment (=) has higher precedence than comma
Well, this is about operator precedence:
c=a,b
is
equivalent to
(c=a),b
The point is, the "," operator will return the second value.
Thus
c=a,b
assigns a to c and returns b
d=(a,b)
returns b and assigns it to d
The comma operator evaluates all its operands, then yields the value of the last expression.

Unclear behavior of "," operator in C

In a given code I found following sequence,
data = POC_P_Status, TE_OK;
I don't understand what that does mean.
Does the data element receive the first or the second element or something else?
Update:
I read somewhere that this behavior is like this,
if i would write that:
if(data = POC_P_Status, TE_OK) { ... }
then teh if clause will be true if TE_OK is true.
What do you mean?
It stores POC_P_Status into data.
i = a, b; // stores a into i.
This is equivalent to
(i = a), b;
because the comma operator has lower precedence than assignment.
It's equivalent to the following code:
data = POC_P_Status;
TE_OK;
In other words, it assigns POC_P_Status to data and evaluates to TE_OK.
In your first case, the expression stands alone, so TE_OK is meaningful only if it's a macro with side effects. In the second case, the expression is actually part of an if statement, so it always evaluates to the value of TE_OK. The statement could be rewritten as:
data = POC_P_Status;
if (TE_OK) { ... }
From the C11 draft (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf) :
The left operand of a comma operator is evaluated as a void
expression; there is a sequence point after its evaluation. Then the
right operand is evaluated; the result has its type and value. If
an attempt is made to modify the result of a comma operator or to
access it after the next sequence point, the behavior is undefined.
That means that in the expression:
a, b
The a is evaluated and thrown away, and then b is evaluated. The value of the whole expression is equal to b:
(a, b) == b
Comma operator is often used in places where multiple assignments are necessary but only one expression is allowed, such as for loops:
for (int i=0, z=length; i < z; i++, z--) {
// do things
}
Comma in other contexts, such as function calls and declarations, is not a comma operator:
int func(int a, int b) {...}
^
|
Not a comma operator
int a, b;
^
|
Not a comma operator

In C what exactly happens if i use () to initialize a double dimension array instead of the {}?

When I initialize an array a[][]:
int a[2][5]={(8,9,7,67,11),(7,8,9,199,89)};
and then display the array elements.
Why do I get:
11 89 0 0 0
0 0 0 0 0
What happens if you use curly braces instead of the first brackets here?
(8,9,7,67,11)
is an expression using the comma operator that evaluates to 11. The same holds for the other initialiser. So you only initialise the first two elements explicitly, all others are then initialised to 0. Your compiler should warn about a missing level of braces in the initialiser.
If you use curly braces, you initialise the two component arrays of a, as is probably intended.
int a[2][5]={(8,9,7,67,11),(7,8,9,199,89)};
is equivalent to (at block scope):
int a[2][5]={11, 89};
, is the C comma operator. It evaluates its operands from left to right and yields the value of the right operand.
At file scope array initializers must be constant and as the , expression is never a constant expression, you array declaration is invalid.
Because you're not using braces, but parentheses. You want:
int a[2][5] = { { 8,9,7,67,11 }, { 7,8,9,199,89 } };
// ^^^ ^^^^^^ ^^^
In your original code, you've just made acquaintance with the comma operator, and you've actually written int a[2][5] = { 11, 89 };. This is legal, but it initializes all missing elements to zero.
It's the concept of comma operator and comma separator
You must have to use {} to initialize array
int a[2][5]={(8,9,7,67,11),(7,8,9,199,89)};
here (8,9,7,67,11) is equivalent to 11 because of comma operator
and (7,8,9,199,89) is equivalent to 89 for the same because comma operator is evaluated to left to right and the right most value is the value returned
hence it's equivalent to a[2][5]={11,89}
but (8,9,7,67,11),(7,8,9,199,89) but comma used in () , () is comma separator

Using macro results in incorrect output when used as part of a larger math expression - why does this happen?

This is a normal C routine program which i found out in some question bank. It is shown below:
#define CUBE(p) p*p*p
main()
{
int k;
k = 27 / CUBE(3);
printf("%d", k);
}
As per my understanding and knowledge the value of K should be 1 as CUBE(3) would be replaced by 3*3*3 during preprocessing and after the subsequent compilation it would be giving the value of 1, but instead it has shown the value of 81 which has made me curious to know how it happened.
Can anyone please justify the answer of 81 to this question above.
The preprocessor merely substitutes
CUBE(3)
with
3*3*3
So you end up with:
k=27/3*3*3
Which, evaluated left-to-right with operator precedence, is in fact 81.
If you add parenthesees around the macro, you should find the results are correct:
#define CUBE(p) (p*p*p)
It would be even better to surround each instance of p with parenthesees as well, as in:
#define CUBE(p) ((p)*(p)*(p))
Which will allow you to pass expressions to the macro correctly (for example, 1 + 2).
Because of operator precedence 27/3*3*3 = 81
You could use instead:
inline int cube(int p) { return p*p*p; }
Preprocessors should be parenthesized properly. Replace it with
#define CUBE(p) ((p)*(p)*(p))
and see.
C macros do textual substitution (i.e. it's equivalent to copying and pasting code). So your code goes from:
k=27/CUBE(3);
to
k=27/3*3*3;
Division and multiplication have the same precedence and have left-to-right associativity, so this is parsed as:
k=((27/3)*3)*3;
which is 9 * 3 * 3 = 81.
This is why C macros should always be defined with liberal use of parentheses:
#define CUBE(p) ((p) * (p) * (p))
For more information, see http://c-faq.com/cpp/safemacros.html from the comp.lang.c FAQ.
Your macro is not protected. Try
#define CUBE(p) ((p)*(p)*(p))
The current macro was expanded to
k=27/3*3*3
which is ((27/3)*3)*3
Because macros are a textual substitution, that works out to:
k = 27 / 3 * 3 * 3;
Since multiplication and division happen left to right, that works out to:
k = ((27 / 3) * 3) * 3;
So, you want to change that in two ways:
#define CUBE(p) ((p)*(p)*(p))
The outer parentheses cause the multiplications to be done before any other operations.
The parentheses around the individual p's are for the case where you do:
CUBE(1 + 2);
Without those inner parentheses, operator precedence will trip you up.
k=27/CUBE(3); => k=27/3 * 3 * 3;
Do you see it? CUBE should be defined like this instead:
#define CUBE(p) ((p)*(p)*(p))
When you do macros, you have to be careful about how you place parentheses. In this case, you don't have any, so the expression becomes 27/3*3*3, which by the precedence rules of / and * becomes (27/3)*3*3.
27/3*3*3 = 9*3*3 = 81 ?
Both / and * operators have the same precedence. To execure 3*3*3 first, you shoudl enclose them in parenthesis.
#include <stdio.h>
#define CUBE(p) p*p*p
int
main ()
{
int k;
k=27/(CUBE(3));
printf("%d",k);
return 0;
}
#define CUBE(p) p*p*p
main()
{
int k;
k=27/CUBE(3);
printf("%d",k);
}
As per my understanding and knowledge the value of K should be 1 as CUBE(3) would be replaced by 3*3*3 during preprocessing
YES
and after the subsequent compilation it would be giving the value of 1,but instead it has shown the value of 81 which has made me curious to know how it happenned.
NO,
k= 27/3*3*3
=(((27/3)*3)*3) (The precedence of `*` and `/` are same but the associativity is from left to right)
=((9*3)*3) =81
Replace #define CUBE(p) p*p*p with #define CUBE(p) ((p)*(p)*(p))
its the way in which the associativity and precedence of operators is implemented.
when the expression is expanded it becomes
27/3*3*3 and not 27/(3*3*3)
now, division and multiplication both have the same precedence in C but the associativity is left to right for both.
so it can be shown as :
(27/3)*3*3 which in turn equals (9*3)*3 = 81
also, if u remember the old arithmetic rule of BODMAS(Bracket Off Division Multiplication Addition Subtraction), this is the order of precedence, then we do division first and then multiplication.
so again we get answer as 81 for 27/3*3*3.
Hi answer for this is:81
Explanation:
In step k=27/cube(3)
cube(3) is replaced by 3*3*3 by preprocessor.then above statement becomes as k=27/3*3*3
in that 27/3 expression is evaluated by c compiler(operator precedence)
the result is(27/3) :9
the statement k=27/3*3*3 becomes as k=9*3*3;
the result for above statement is 81:

Resources