Can sombody explain how this works?
int x, y;
....
(some_condition ? x : y) = 100;
Is this intended to work or is is just a "blind" translation or the compiler (something like vec[10] equals 10[vec])?
This is valid C++ and invalid C.
The result of a conditional expression can be (and in this case is) an lvalue in C++ refering to one of x or y depending on whether some_condition evaluates to true. In C++ either x is assigned the value 100 if some_condition is true when converted to a bool, otherwise y is assigned 100.
In C, the result of a conditional expression is never an lvalue and cannot be assigned to.
At least in C++, that code snippet is essentially equivalent to this:
if(some_condition)
{
x = 100;
}
else
{
y = 100;
}
It is guaranteed by the C++ standard, although you have to read the relevant sections carefully. The rules of the operator are surprisingly complicated (mainly due to the type conversions that are performed) so the conditional operator and the if-then-else statement are not exactly equivalent all the time.
However, in your code snippet above, this paragraph in the standard is relevant:
5.16/4 Conditional operator:
If the second and third operands are lvalues and have the same type, the result is of that type and is an lvalue.
It is an expression which has the same result as this code:
if (some_condition)
x = 100;
else
y = 100;
if x and y are l-value, the ternary expression is an l-value.
Discussed here
No, it is a short form for a if condition. It is like
if(somecondition)
{
x = 100;
}
else
{
y = 100;
}
x and y are both lvalue of the same type.
I do not think that there is something blind in this code.
But you may find some compiler that cannot compile this code.
I usually prefer use if/else code which produce exactly the same code and is far more readable for maintainers.
And if you want to track bug it easier to put each branch on separate branch it is easier to set break points.
Code coverage control is also easier to check.
you assign to either x or y depending on the condition.
It looks like a ternary operator selecting an lvalue. I didn't know that could be done, but I suppose it rather makes sense. Based on the condition, one of the two values (x or y) will be assigned the number 100.
Very cool if it works!
It is intended to work.
The ternary operator ?: can produce an lvalue (i.e. something you can assign to) if both of its possible results are lvalues, as they are in your example.
So your example assigns a value to either x or y depending on some other value.
The value of x or y being replaced with 100 depends on the condition. It is also generally used while returning -
return condition ? x : y ; // If condition is true => return x else return y
Related
My question is maybe very simple, but I'm wondering what does this x+1 means?
Let's see an example:
int main()
{
int x = 2;
x + 1; //1
if ((x - 2) && (x = 7)) { //2 and 3
// do something
}
}
What i know:
That the assignment cannot be evaluated because left side of && will return false, so the conjunction will never be true.
Questions:
How does the memory looks like after operation 1?
Is the value of x changed after x-2 (2)?
I saw in debugger that this doesn't change the value of x, but I'm using a C++ compiler in Visual Studio so it can give another values.
Thanks in advance :)
The code
x+1;
evaluates the expression and then just drops the results. It's legal but a good compiler should issue a warning (IIRC g++ emits something about an expression that would require side effects to be useful).
The code (x - 2) && (x = 7) instead doesn't do anything, because && is "short-circuited" and x-2 is false in a logical context. So the code (x = 7) is not evaluated. && and || evaluate the left side first and the right side is evaluated only if the result cannot be determined from it... for example (1 || foo()) is guaranteed to skip the call to function foo.
Code like
y = (x - 2) * (x = 7);
would instead be undefined behavior because C++ is not required to work through sub-expressions in sequence (except for the comma operator ,, logical AND &&, logical OR|| and the ternary operator ?:) and using and modifying the same value in different parts of an expression (if these parts don't have a prescribed evaluation sequence) is not permitted but the compilers are not required to complain about it. Whatever happens happens, and it's a programmer's fault.
How does the memory looks like after operation 1?
It's the same as before the operation. x - 1 is an expression without side-effects (i.e. it doesn't modify any variable). The statement x - 1; evaluates the expression and discards the result. Any decent compiler will optimize it away.
To increment x by 1 you should use the compound assignment operator +=:
x += 1;
The same can be achieved with the increment operator ++:
x++; // these do the same
++x; // thing in this case
In other contexts, the two different versions of ++ have different meaning, see What is the difference between prefix and postfix operators?.
Is the value of x changed after x-2 (2)?
x - 2 itself doesn't change the value of x. (Again x -= 2 can be used to achieve that.)
However the assignment x = 7 changes the value of x to 7, if the assignment is evaluated (which happens if the left-hand-side of && evaluates to true or non-zero (this is called short-circuit evaluation). In this case the left-hand-side evaluates to zero so x = 7 is not evaluated).
Note that the = operator is different to the equality comparison operator ==:
x == 7 // evaluates to `true` if the value of `x` is equal to `7`, and to `false` otherwise.
It means "perform this calculation and throw away the result".
In your case that means the compiler will probably just remove the code completely (since it obviously has no side effects). But if operator+ had been overloaded and/or user-defined types had been involved, then there could be meaningful side-effects and the code could be meaningfull and would be kept to perform those operations..
x + 1 does not change value of x. The result of x + 1 viz 3 is calculated and the result is then ignored.
For and (&&) sequence of evaluation is left to right. As long as the components of && operator are true, the next component is evaluated.
As stated earlier for x + 1, similarly, x + 2 does not change value of x. In your case, x - 2 results into 0 viz. zero and so the next component is not evaluated.
The basic principles of C language, remain same across all compilers and IDE (in your case Visual Studio) has no effect on the compilation
I have a question on a program that includes the following if statement:
if (x =+ 4){
x += 5;
}
I've never seen anything like that before, surely it isn't a typo? Does =+ actually do anything?
x =+ 4
means
x= (+4)
or simply
x=4
though such construction syntactically correct and can be compiled, does not make much sense and most probably a typo, where x==4 was intended, especially that it is used as condition for if
In the early days of C, =+ was the same as +=, but that's long gone and never made its way into C++.
=+a is understood to be = (+a)
The unary + operator promotes the argument to an int if it's of a narrower type, otherwise it's a no-op.
And = is regular assignment.
You can contrive a difference between =+ and = in this way:
If = was twice overloaded for two particular pairings, for example {Foo, int} and {Foo, char}, and you had an instance of Foo foo and a char c, then
foo = c // calls the overload taking a `char`
and
foo =+ c // calls the overload taking an `int`
would call different overloads.
Sorry, my initial answer was due to foolishly misreading the question.
The correct answer, is this code simply assigns x the value of positive 4,
because this is then non zero it satisfies the if and increments it further by 5.
A simpler form of this program in its current state would be:
x = 9;
However I strongly suspect there was a typo involved and the statement inside the if condition should either be x == 4, x += 4 or x != 4 depending on context.
OK just to round this out, I did find that my hunch was right, =+ and =- are indeed just obsolete forms of the += and -= op's in use today:
Stack Overflow: What does =+ mean in C?
https://www.cs.auckland.ac.nz/references/unix/digital/AQTLTBTE/DOCU_064.HTM (now that's a vintage web page!)
and specifically
https://en.wikipedia.org/wiki/C_(programming_language)#K.26R_C
tells us that they were changed: "Compound assignment operators of the form =op (such as =-) were changed to the form op= (that is, -=) to remove the semantic ambiguity created by constructs such as i=-10, which had been interpreted as i =- 10 (decrement i by 10) instead of the possibly intended i = -10 (let i be -10)."
So it's not to do with making an argument explicitly +ve or -ve. You can simply substitute the modern forms, eg use += in place of =+.
I came across this code line in C:
#define RUNDE(n) ( K ^= Q[n], y = K, K = F(K) ^ xR, xR = y )
Is it valid to assign something to K multiple times? I thought it's invalid to change a variable more than one time in one statement.
Is it valid to assign something to K multiple times?
That's perfectly valid C macro. A comma operator , is used here.
Using , operator you can assign a value to a variable multiple times.
e.g.K = 20, K = 30; This will assign 30 to K overwriting the previous value of 20.
I thought it's invalid to change a variable more than one time in one statement.
Yes it leads to undefined behavior if we try to modify a variable more than once in a same C statement but here first , is a sequence point.
So it's guaranteed that we will be modifying the K second time (K = 30) only when all the side effects of first assignment (K = 20) have taken place.
This is well-defined as the comma operator evaluates its first operand before its second.
However, IMHO this code is horrible and you shouldn't write it. inline functions exist to do things like this; using the preprocessor is just abuse. Sure, you would need to pass some arguments to an inline function, but this is far preferable to relying on names from the surrounding scope.
In C++ this would be regarded as nasty; in C it's permissible as the reliance on the preprocessor is more necessary.
But in either case your expression is perfectly well-defined. The comma operator (which is evaluated from left to right), acts as a sequenced expression separator.
The elegant thing with this macro is that its value is the value of xR = y, which is the final value of y.
But the inelegance of this macro, such as using variable names that are not passed as arguments, probably outweighs any benefits. My inclination is to bin it.
It is a valid comma operator, that perform all statements in sequence, returning the value of the last statement.
That macro is a sequence of assignments, using the last assignment (y or xR) as return value
I was wondering whether the access to x in the last if below here is undefined behaviour or not:
int f(int *x)
{
*x = 1;
return 1;
}
int x = 0;
if (f(&x) && x == 1) {
// something
}
It's not undefined behavior as operator && is a sequence point
It is well defined.
Reference - C++03 Standard:
Section 5: Expressions, Para 4:
except where noted [e.g. special rules for && and ||], the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is Unspecified.
While in,
Section 1.9.18
In the evaluation of the following expressions
a && b
a || b
a ? b : c
a , b
using the built-in meaning of the operators in these expressions, there is a sequence point after the evaluation of the first expression (12).
It is defined. C/C++ do lazy evaluation and it is defined that first the left expression will be calculated and checked. If it is true then the right one will be.
No, because && defines an ordering in which the lhs must be computed before the rhs.
There is a defined order also on ||, ?: and ,. There is not on other operands.
In the comparable:
int x = 0;
if (f(&x) & x == 1) {
// something
}
Then it's undefined. Here both the lhs and rhs will be computed and in either order. This non-shortcutting form of logical and is less common because the short-cutting is normally seen as at least beneficial to performance and often vital to correctness.
It is not undefined behavior. The reason depends on two facts, both are sufficient for giving defined behavior
A function call and termination is a sequence point
The '&&' operator is a sequence point
The following is defined behavior too
int f(int *x) {
*x = 1;
return 1;
}
int x = 0;
if (f(&x) & (x == 1)) {
// something
}
However, you don't know whether x == 1 evaluates to true or false, because either the first or the second operand of & can be evaluated first. That's not important for the behavior of this code to be defined, though.
It's not undefined, but it shouldn't compile either, as you're trying to assign a pointer to x (&x) to a reference.
&& will be evaluated from left to right (evaluation will stop, if the left side evaluates false).
Edit: With the change it should compile, but will still be defined (as it doesn't really matter if you use a pointer or reference).
It will pass the address of the local variable x in the caller block as a parameter to f (pointer to int). f will then set the parameter (which is a temporary variable on the stack) to address 1 (this causes no problem) and return 1. Since 1 is true, the if () will move on to evaluate x == 1 which is false, because x in the main block is still 0.
The body of the if block will not be executed.
EDIT
With your new version of the question, the body will be executed, because after f() has returned, x in the calling block is 1.
How are the below valid and invalid as shown and what do they mean. When would such a situation arise to write this piece of code.
++x = 5; // legal
--x = 5; // legal
x++ = 5; // illegal
x-- = 5; // illegal
The postfix (x++/x--) operators do not return an lvalue (a value you can assign into).
They return a temporary value which is a copy of the value of the variable before the change
The value is an rvalue, so you could write:
y = x++ and get the old value of x
Given that both operator=() and operator++() can be overloaded, it is impossible to say what the code does without knowing more about the type of thing the operators are being applied to.
Those all modify the value of x more than once between sequence points, and are therefore undefined behavior, which you should carefully avoid. I don't see where the distinction between "legal" and "illegal" comes in - since the behavior is legal, any behavior (including sending assorted email to the Secretary of State) is perfectly in accordance with the Standard.
Assuming that the question is about built-in ++ and -- operators, none of these statements are strictly legal.
The first two are well-formed, i.e. they merely compilable because the result of prefix increment is lvalue. The last two are ill-formed, since the result of postfix increment is not a rvalue, which is why you can't assign to it.
However, even the first two are not legal in a sense that they produce undefined behavior. It is illegal to modify the same object more than once without an intervening sequence point. (Note also, that compilers are allowed to refuse to compile well-formed code that produces undefined behavior, meaning that even the first pair might prove to be non-compilable).
++x and --x both give you back x (after it's been incremented/decremented). At that point you can do what you want with it, including assign it a new value.
x++ and x-- both give you back what x was (just before it was incremented/decremented). Altering this value makes no more sense than changing any ordinary function's return value:
obj->getValue() += 3; // pointless
Frankly, you should never write that. Postincrement and pre-increment (and decrements) should only ever be used on their own. They're just recipes for confusion.
The only place I can think of where such a situation would occur is with an operator overload of operator++ and operator=. Even then, the definition isn't clear. What you code is saying basically is add one to x, then assign 5 to it. A question would arise such as why would you need to increment x before assigning 5 to it? The only possible explanation is if you have some sort of class where the ++ operator somehow increment an internal counter, then the assignment. No idea why such a thing is needed though.