This question already has answers here:
How does comma operator work during assignment?
(5 answers)
Closed 6 years ago.
Can anybody explain for me:
int a, b, c, d;
a = 2;
b = 4;
c = a, b;
d = (a, b);
Why c == 2 and d == 4 ???
The two statements are both evaluated as
c = a;
d = b;
due to how the comma operator (which has the lowest precedence of any operator) works in C and C++.
For the first one, c = a is evaluated first (as = has higher precedence than the comma operator) then b (which is a no-op) is evaluated. The entire expression has a value b but that's not assigned to anything.
For d = (a, b);, (a, b) is first evaluated due to the parentheses. This has a value b, and that is assigned to d.
Related
This question already has an answer here:
Why doesn't C++ have the ~= and != operators? [closed]
(1 answer)
Closed 5 years ago.
int main()
{
unsigned int a = 0;
unsigned int b = 0;
a ^= b; // ok
a |= b; // ok
a &= b; // ok
a = ~b; // ok
a ~= b; // error : expected ';' after expression
}
^=, |=, and &= are all legal.
Why isn't ~= legal in C++?
Because ~ is an unary operator, not binary.
The short form op= applies to binary operators only, when the first operand is the destination.
~ is only ever a unary operator.
The contraction of a = a # b to a #= b for an arbitrary operator # only makes sense if it takes two arguments; i.e. if # is a binary operator.
Why isn't ~= legal in C++?
That's because C++ does not contain an ~= operator; ~= are just two separate tokens.
As for why C++ wasn't designed that way, you'd have to ask the designer, but I think it's safe to say that it's because C++ was based on C originally and has the same operators as C, with only a few new operators added for the new language features (i.e. :: and ->*).
So you should probably ask this question again for C.
Because the "operator assignments" (like +=, ^=) are based on the original operation having two operands.
For example, a + b has two operands of +, and a += b gives the same net effect as a = a + b.
Operator ~ is a unary operator i.e. it accepts one operand. So a = ~b makes sense, but a = a~b does not. Since a = a~b doesn't make sense, neither does a ~= b.
This question already has answers here:
What does the operation c=a+++b mean?
(9 answers)
Why doesn't a+++++b work?
(9 answers)
Closed 9 years ago.
Given the following code:
int a=0,b=1;
int r=a+++b;
which are the operations performed and in which order?
a++ + b
a + ++b
I this compiler specific or does it depend on the standard?
It is (a++) + b but not because of operator precedence.
It is parsed as (a++) + b because the compiler takes the longest token it can from a sequence of characters. In other words, the lexer keeps reading characters until it encounters something that can't be part of the same token as what it already has.
This is also how it interprets >= as one token instead of > and =, and double as 'double' not 'do uble'.
There are rules of operator precedence for statements like
a || b && c
// "a || (b && c)" NOT "(a || b) && c", because && takes precedence
However, in your case the operators ++ and + have already been determined. Once the operators have been determined, the rules of operator precedence can apply.
There are some good answers to Why doesn't a+++++b work in C? that should explain this in more detail.
That is governed by the operator precedence. Since postfix ++ has a higher precedence than the + operator it binds tighter to a is post incremented then added to b so the result is:
(a++) + b
I read somewhere that the ?: operator in C is slightly different in C++, that there's some source code that works differently in both languages. Unfortunately, I can't find the text anywhere. Does anyone know what this difference is?
The conditional operator in C++ can return an lvalue, whereas C does not allow for similar functionality. Hence, the following is legal in C++:
(true ? a : b) = 1;
To replicate this in C, you would have to resort to if/else, or deal with references directly:
*(true ? &a : &b) = 1;
Also in C++, ?: and = operators have equal precedence and group right-to-left, such that:
(true ? a = 1 : b = 2);
is valid C++ code, but will throw an error in C without parentheses around the last expression:
(true ? a = 1 : (b = 2));
The principal practical difference is that in C, evaluation of ?: can never result in a l-value where as in C++ it can.
There are other differences in its definition which have few practical consequences. In C++ the first operand is converted to a bool, in C it is compared against 0. This is analagous to the difference in definition of ==, !=, etc. between C and C++.
There are also more complex rules in C++ for deducing the type of a ?: expression based on the types of the 2nd and 3rd operands. This reflects the possibility of user-defined implicit conversions in C++.
Example code. Valid C++; invalid C.
extern int h(int p, int q);
int g(int x)
{
int a = 3, b = 5;
(x ? a : b) = 7;
return h( a, b );
}
gcc generates the error: "error: invalid lvalue in assignment" when compiling as C, but the code compiles without error when compiling as C++.
Edit:
Although ?: can't return an l-value in C, perhaps surprisingly the grammar for ?: is:
conditional-expression:
logical-OR-expression
logical-OR-expression ? expression : conditional-expression
This means that a ? b : c = d parses as (a ? b : c) = d even though (due to the 'not an l-value' rule) this can't result in a valid expression.
C++ changes the grammar to this:
conditional-expression:
logical-or-expression
logical-or-expression ? expression : assignment-expression
While the extension to allow conditional-expression to be an l-value in some situations would have made a ? b : c = d valid without the grammar change, the new grammar change means that the expression is now valid but with the different meaning of a ? b : (c = d).
Although I don't have any evidence for it, my supposition that as the grammar change couldn't break compatibility with existing C code, it was more likely that the new grammar would produce fewer surprises with expressions such as:
make_zero ? z = 0 : z = 1;
When you define operators as datatype in SML, do they act as functions as operators?
like datatype egexp= egadd of egexp*egexp
does egadd act as operator or function? I mean do I write the expression a+b as egadd(a)(b) or (a)egadd(b)?
Thank You
You are essentially asking about infix syntax. This actually has nothing to do with functions vs constructors, both can either be infix or (by default) nonfix:
fun f (x, y) = ...
val a = f (1, 2)
infix f
val b = 1 f 2
datatype t = C of int * int
val c = C (1, 2)
infix C
val d = 1 C 2
This applies uniformly to alphanumeric and symbolic identifiers:
fun ++ (x, y) = ...
val a = ++ (1, 2)
infix ++
val b = 1 ++ 2
datatype t = && of int * int
val c = && (1, 2)
infix &&
val d = 1 && 2
That is, there is no distinction between 'functions' and 'operators' in SML. You just have nonfix vs infix identifiers.
You write neither. It acts on a "function" (actually, as a value constructor), taking the types you specified.
That is, since you specified that egadd takes an egexp * egexp, it takes a tuple of two egexps, that is: egadd (a, b), where a and b are values of the type egexp.
If desired, you can make it infix like any other function by using infix or infixr.
egadd is a "constructor". egexp is an algebraic data type, and egadd is one of its constructors. Constructors in SML can either have no arguments, or one argument (multiple "components" can be packed into 1 tuple argument). As a constructor with an argument, egadd is also a function that takes an argument of that argument type (egexp*egexp) and returns ("constructs") a value of the algebraic data type egexp. For example, as #SebastianPaaskeTørho mentioned, if a and b are values of type egexp, then egadd (a, b) constructs a new value of type egexp.
I read somewhere that the ?: operator in C is slightly different in C++, that there's some source code that works differently in both languages. Unfortunately, I can't find the text anywhere. Does anyone know what this difference is?
The conditional operator in C++ can return an lvalue, whereas C does not allow for similar functionality. Hence, the following is legal in C++:
(true ? a : b) = 1;
To replicate this in C, you would have to resort to if/else, or deal with references directly:
*(true ? &a : &b) = 1;
Also in C++, ?: and = operators have equal precedence and group right-to-left, such that:
(true ? a = 1 : b = 2);
is valid C++ code, but will throw an error in C without parentheses around the last expression:
(true ? a = 1 : (b = 2));
The principal practical difference is that in C, evaluation of ?: can never result in a l-value where as in C++ it can.
There are other differences in its definition which have few practical consequences. In C++ the first operand is converted to a bool, in C it is compared against 0. This is analagous to the difference in definition of ==, !=, etc. between C and C++.
There are also more complex rules in C++ for deducing the type of a ?: expression based on the types of the 2nd and 3rd operands. This reflects the possibility of user-defined implicit conversions in C++.
Example code. Valid C++; invalid C.
extern int h(int p, int q);
int g(int x)
{
int a = 3, b = 5;
(x ? a : b) = 7;
return h( a, b );
}
gcc generates the error: "error: invalid lvalue in assignment" when compiling as C, but the code compiles without error when compiling as C++.
Edit:
Although ?: can't return an l-value in C, perhaps surprisingly the grammar for ?: is:
conditional-expression:
logical-OR-expression
logical-OR-expression ? expression : conditional-expression
This means that a ? b : c = d parses as (a ? b : c) = d even though (due to the 'not an l-value' rule) this can't result in a valid expression.
C++ changes the grammar to this:
conditional-expression:
logical-or-expression
logical-or-expression ? expression : assignment-expression
While the extension to allow conditional-expression to be an l-value in some situations would have made a ? b : c = d valid without the grammar change, the new grammar change means that the expression is now valid but with the different meaning of a ? b : (c = d).
Although I don't have any evidence for it, my supposition that as the grammar change couldn't break compatibility with existing C code, it was more likely that the new grammar would produce fewer surprises with expressions such as:
make_zero ? z = 0 : z = 1;