Comma(,) operator suppress the precedence of parentheses in C - c

I just started reading C.
Situation :
x = ( y = 3, ( z = ++y + 2 ) + 5 )
It is evaluating y = 3 first then evaluating ( z = ++y + 2 )
My Problem :
It should first evaluate ( z = ++y + 2 ) because the precedence of comma(,) is much less than parenthesis
My way of Thinking :
Due to precedence we select outer parenthesis
Then we need to evaluate parenthesis
Under this (parenthesis) I again started applying precedence rule
So I took inner bracket to evaluate first
P.S. :
This is not a Duplicate
I have already gone through these links but still unable to understand
Behavior of comma operator in C
C comma operator
What does the comma operator , do?
https://learn.microsoft.com/en-us/cpp/cpp/comma-operator
Uses of C comma operator
https://en.wikipedia.org/wiki/Comma_operator

You're confusing operator precedence with order of evaluation.
Operator precedence dictates how subexpressions are grouped. It does not dictate when each operand is evaluated.
The comma operator has a sequence point between its left operand and its right operand. In the case of y = 3, ( z = ++y + 2 ) + 5, that means that y = 3 must be fully evaluated before ( z = ++y + 2 ) + 5 can be evaluated.
Note also in the subexpression ( z = ++y + 2 ) + 5 that there is no guarantee that everything inside the parenthesis are evaluated before everything inside. You only know that ( z = ++y + 2 ) and 5 are evaluated before ( z = ++y + 2 ) + 5 is evaluated. If for example you had (z = ++y + 2) + y this would invoke undefined behavior because the second y could be evaluated before or after the side effect of ++y.
As another example, if you had x = (func1() + 3) + func2(), either func1 could be called first or func2 could be called first since the order of evaluation of operands is unspecified. If both of those functions modified the same global variable, you wouldn't be able to reliably know the value of that variable.

Precedence and evaluation order are different things. In the expression (a*b) - (c+d), the compiler is free to evaluate (c+d) before (a*b), even though multiplication has higher precedence than addition. But in the expression a,b, as well as the code a;b, the compiler is required to sequence the computation of a before the computation of b.

You are confused between Precedence and Order of Evaluation. Precedence is the priority for grouping different types of operators with their operands.
The comma (,) operator constitute Sequence Point and therefore guarantee a particular order of evaluation for their operands which is left to right.
Order of evaluation
Ordering
......
If a sequence point is present between the subexpressions E1 and E2, then both value computation and side effects of E1 are sequenced-before every value computation and side effect of E2
Rules
.....
2) There is a sequence point after evaluation of the first (left) operand and before evaluation of the second (right) operand of the following binary operators: && (logical AND), || (logical OR), and , (comma).
In this expression:
x = ( y = 3, ( z = ++y + 2 ) + 5 )
First y = 3 will be evaluated first and then ( z = ++y + 2 ) + 5.

Related

Why my for loop works with "&&" and not with ","

I am stuck at this exercise of c program that have a comma in C for loop if, I replace , with && it works same
for(i = 5, j = i - 1 ; i > 0 , j > 0 ; --i ,j = i - 1)
printf("\n%d",i);
In this loop I get how for( i = 5,j = i - 1 ; ? ; --i ,j= i - 1) but the part where ? is there I don't get how that is working 1,1 = true ? 1,0 = false ? C is trick that's why love it 3> can you explain me how that part is working
but the part where ? is there i don't get how that is working
The comma operator in C evaluates the expression before the comma, and then the expression after the comma, and then returns the value of the expression after the comma. So the value of the expression 1, 0 in C is 0. The result of 1, 1 is 1. The result of foo(x), bar(x) is the value of bar(x).
This doesn't come up very often because in practice, the comma operator isn't used all that often. It can be handy in a few cases, such as in for or while loops where you might want to manipulate more than one variable each time through the loop. But in general, combining expressions with the comma operator just creates uncertainty about how those expressions will be evaluated, what the result of the overall expression is, and so on. Whenever possible, separate the expressions and execute them one at a time.
Why my for loop works with "&&" and not with ","
The && operator combines (using logical AND) the result of both expressions instead of throwing the result of the first expression away, so depending on the expression you can get a different result than you do with ,. 1 ? 0 and 1 ? 1 give the same result for both , and && because the result of the && depends on the second expression in both cases. But 0 ? 0 and 0 ? 1 will give different results — , again returns the value of the second expression, and && returns 0 because both expressions are considered and 0 AND anything is 0.
; i > 0 , j > 0 ;
Formally, the "," is know as the Comma operator:
The comma operator expression has the form
lhs , rhs
where
lhs - any
expression rhs - any expression other than another comma operator (in other words, comma operator's associativity is left-to-right)
First, the left operand, lhs, is evaluated and its result value is discarded. Then, a sequence point takes place, so that all side effects of lhs are complete. Then, the right operand, rhs, is evaluated and its
result is returned by the comma operator as a non-lvalue.
More informally, in ;i > 0 , j > 0; the i > 0 is evaluated and ignored to determined if the loop should or not terminate, and then j > 0 is evaluated and its value is used to determined if the loop should (or not) continue.
I am stuck at this exercise of c program that have a comma in C for
loop if, I replace , with && it works same
In this case it works the same with "," or "&&" because when i = 1 then j = 0 and consequently j > 0 evaluates to false and you exit the loop. When j > 0 evaluates to false i > 0 also evaluates to false, hence the reason why in your case it is the same using i > 0 && j > 0 or i > 0 , j > 0. Nevertheless, i > 0 && j > 0 and i > 0 , j > 0 are not semantically the same.
In your case:
for(i = 5, j = i - 1 ; i > 0 && j > 0 ; --i ,j = i - 1)
actually, you can simplified i > 0 && j > 0 to just i > 0 since whenever j > 0 evaluates to false i > 0 will also evaluate to false since j = i - 1.

Preprocessor macro in C

I am new to C programming, in fact programming at all, and recently learn the use of macros with regard to preprocessor directives. Although I am getting more familiar with it the following exercise that I got from a textbook stumbles me since I do not get the solution or the general "take-away lesson" from it.
Before I wrote this question here, I tried to execute the code myself by adding some printf() in order to obtain the correct answers but it does not even compile. Now, before I write down the question and code I want to make it explicit that this is a self-learning question and that I do not want to offend people here with a question that many will find trivial. I just want to understand what is going on.
The code is as follows
int x=2, y=3, a=4,b=5;
#define MAX(x, y) x > y x : y
int c,d,e,f;
c = MAX( a, 3 );
d = MAX( y, x );
e = MAX( ++x, 1 );
f = MAX( b, MAX (6, 7) );
I am asked to give the values of c,d,e and f. There is an additional hint that although it is named that way the above macro is NOT the maximum operator. Therefore, I don't think the "obvious" guess of e.g. max(a,3) = 4 is correct. Consequently, I don't know what is going on.
EDIT: I forgot to mention: I know that there are parentheses missing for the correct use. But I am specifically asked to evaluate the terms without them. Therefore I am confused since I do not know exactly how the results change and the function behave without those included.
Expanding the macro as-is, we get the following:
Original Expanded
-------- --------
c = MAX( a, 3 ); c = a>3 a : 3;
d = MAX( y, x ); d = y>x y : x;
e = MAX( ++x, 1 ); e = ++x>1 ++x : 1;
f = MAX( b, MAX (6, 7) ); f = b>MAX (6, 7) b : MAX (6, 7);
f = b>6>7 6 : 7 b : 6>7 6 : 7;
Macro expansion is just dumb text substitution - syntax, scope, precedence, associativity, values, side effects, etc., are simply not taken into account when a macro is expanded (macro expansion occurs before the source code is fed to the compiler proper).
Obviously, none of the expanded expressions above will compile. For that to happen, we need to fix the MAX macro by defining it as
#define MAX( x, y ) x>y ? x : y
Now we get the following:
Original Expanded
-------- --------
c = MAX( a, 3 ); c = a>3 ? a : 3;
d = MAX( y, x ); d = y>x ? y : x;
e = MAX( ++x, 1 ); e = ++x>1 ? ++x : 1;
f = MAX( b, MAX (6, 7) ); f = b>MAX (6, 7) ? b : MAX (6, 7);
f = b>6>7 ? 6 : 7 ? b : 6>7 ? 6 : 7;
Better. The expanded expressions above will compile, but the last two don't do anything like what you expect them to. e won't get the max of x and 1, it will either get x+2 or 1 (? introduces a sequence point, so the behavior isn't undefined). f gets ... something, can't remember the associativity of > and ?: offhand, not really willing to dig it up.
Again, macros don't take precedence and associativity into account when expanding their arguments. Imagine we write a macro CUBE that does the following:
#define CUBE(x) x * x * x
and we call it as
y = CUBE( 2 + 3 );
That expands to
y = 2 + 3 * 2 + 3 * 2 + 3;
which gives us the value 17, when we were probably expecting 125.
The right way to define the MAX macro is
#define MAX( x, y ) ((x) > (y) ? (x) : (y))
We not only parenthesize each argument, we parenthesize the entire expression. This way, precedence and associativity are preserved not only if you pass complex expressions as arguments, but also if you pass this macro as an argument to another one (as in the last example):
Original Expanded
-------- --------
c = MAX( a, 3 ); c = ((a) > (3) ? (a) : (3));
d = MAX( y, x ); d = ((y) > (x) ? (y) : (x));
e = MAX( ++x, 1 ); e = ((++x) > (1) ? (++x) : (1));
f = MAX( b, MAX (6, 7) ); f = ((b) > (MAX (6, 7)) ? (b) : (MAX (6, 7)));
f = ((b) > ((6) > (7) ? (6) : (7)) ? (b) : ((6) > (7) ? (6) : (7)));
This time, f will be evaluated like you expect it to be.
The evaluation of e is still problematic (++x can still be evaluated twice). This is a problem in general with macros that expand their arguments more than once - arguments that have side effects can be evaluated multiple times, which will lead to wrong answers or undefined behavior.
Incorrect use of ternary operator.
#define MAX(x,y) x>y x : y
Should be:
#define MAX(x,y) (x>y) ? x : y
And to allow for more complex expressions:
#define MAX(x,y) (((x)>(y)) ? (x) : (y))
You mention that you don't know what is going on. There is only way - run only the preprocessor.
What compiler are you using? Assuming gcc/clang you can -
gcc -E filename.c
This will only run the preprocessor and let you analyze what is going on.
BTW you code doesn't compile because you made a mistake with the ternary operator - should be x > y ? x : y.

Role of precedence in expression evaluation in C

If y is of integer type, then the expressions:
3*(y-8)/9
and
(y-8)/9*3
Will yield different result always or is it possible for them to yield same result?
What does it depend on?
Explanation with an example will be helpful.
May yield different or same result, it is depend on 'y' value. The operations will be carried from left to right.
Ex: for y=11:
3*(y-8)/9: 1 (y-8)/9*3: 0
for y = 10
3*(y-8)/9: 0 (y-8)/9*3: 0

What will be the DFA for the regular expression 0(0+1)*0+1(0+1)*1?

This is the DFA i have drawn-
Is it correct?
I am confused because q4 state has 2 different transitions for same input symbol which violates the rule of DFA, but I can't think of any other solution.
Your DFA is not correct.
your DFA is completely wrong so I don't comment
DFA for RE:
0(1 + 0)*0 + 1(1 + 0)*1
Language Description: if string start with 0 it should end with 0 or if string start with 1 it should end with 1. hence two final states (state-5, state-4).
state-4 : accepts 1(1 + 0)*1
state-5 : accepts 0(1 + 0)*0
state-1 : start state.
DFA:
EDIT :
+ Operator in Regular Expression
(0 + 1)* = (1 + 0)* that is any string consist of 1s and 0s, including Null string ^.
Here + means Union if it appear between two RE: and A U B = B U A (similarly)=> (0 + 1) = (0 + 1) .
meaning of plus + depends on syntax it appears in: If expression is a+ (+ is superscripted) this means one of more as, and If a+b then + means Union operation either a or b.
a+ : { a, aa, aaa, aaa.....} that is any number of a string in language with length > 1.
I think you should start with 0 first
0(1 + 0)*0 + 1(1 + 0)*1

SQL Server: What does 1 ++ 2 mean?

SQL Server's T-SQL syntax seems to allow multiple plus signs in succession:
SELECT 1 + 2 --3
SELECT 1 ++ 2 --3
SELECT 1 ++++++ 2 --3
SELECT 1 + '2' --3
SELECT 1 ++ '2' --3
SELECT '1' + '2' --'12'
SELECT '1' ++ '2' --'12'
Multiple pluses seem to behave just like a single plus. Why does the "multiple plus operator" ++ exist? What does it do?
The first plus sign is interpreted as an addition operator. Each of the remaining plus signs is interpreted as a unary plus operator:
1 ++ 2 means 1 + (+2)
1 +++ 2 means 1 + (+(+2))
It's very common in programming languages to have this unary plus operator, though it's rarely used in SQL as it doesn't actually do anything.
Although a unary plus can appear before any numeric expression, it performs no operation on the value returned from the expression. Specifically, it will not return the positive value of a negative expression.
The unary plus operator is mentioned in the SQL-92 standard.
As well as the usual arithmetic operators, plus, minus, times, divide, unary plus, and unary minus, there are the following functions that return numbers: ...
While unary plus isn't all that useful, it has a more useful companion: unary minus. It is also known as the negative operator.
SELECT -(expression), ...
-- ^ unary minus
SELECT 1 ++ 2 means 1 plus (+2) which means 3
Same logic for the others 1+(+(+2)) and so on
SELECT '1' + '2' --'12' you are concatenating 2 strings, string '1' and string '2', which results '12'

Resources