what's the different between an expresion like:
int a, b;
bool p = false;
while (cin >> a >> b and not p) { // code }
// and:
int a, b;
bool p = false;
while (not p and cin >> a >> b) { // code }
The difference is that in C++, a shortcut is followed while evaluating boolean conditions.
In case of an and, you know that if the first statement is false, the whole output is false. In this case, the second condition won't be evaluated at all. Similarly, if the first statement in an or statement evaluates to true, then the second isn't evaluated.
So why is this useful, except the small effort saved in evaluating the second statement. One of the cases is AND is wherein you may not want the second expression to be evaluated if the first one is false. A reason for this is that the second expression may be ill defined if the first statement is false.
For example, when accessing vector elements in a while loop, you may have a situation where you are checking some condition. Along with that you'd have to take care to ensure that the index is within the limits of the vector. So you can just write
while (i < vector.size() && condition(vector[i]))
You can see that if the first part evaluates to false, then the program would crash upon accessing vector[i] in the condition. However, it doesn't reach that point. This is just one of the many uses of short-circuiting operators.
Yes the order is important because of short circuit evaluation.
while (cin >> a >> b and not p)
will take in the input and if that operation succeeds then it will evaluate p. If the input fails then we end the loop and never check p. On the other hand:
while (not p and cin >> a >> b)
Will evaluate p and if not p is false then the rest of the condition will not be executed.
Related
Let us say I have an integer array representing the chess pieces on a board;
int board[8][8];
In my chess game, I am currently coding a generator function that will return an integer vector of all legal moves.
Naturally, I will be using if statements
I am at a point where I need to check a certain element in the board relative to a piece on the board
For example, If I have a pawn piece;
board[row][col] == 'p';
I need to generate [row+1][col], [row+2][col] and in some cases if it can attack a piece, a change in column too.
But if a piece is on any edge of the board, board[row+1][col] will return be index out of range
For that reason I need an extra if statement.
My question is, shall i use:
if (pieceisnotonedge && board[row+1][col] == 0)
or
if (pieceisnotonedge)
{
if (board[row+1][col] == 0)
}
For the first example, if pieceisnotonedge returns false, will it also check the next condition? Because if it does, then I am in trouble.
For the first example, if pieceisnotonedge returns false, will it also
check the next condition?
No, it will not. Because the build-in logical operators do short-circuiting. From cppreference.com:
Builtin operators && and || perform short-circuit evaluation (do not
evaluate the second operand if the result is known after evaluating
the first), but overloaded operators behave like a regular function
calls and always evaluate both operands
Therefore, in
if (pieceisnotonedge && board[row+1][col] == 0)
if the pieceisnotonedge is false, the second will not be evaluated. Therefore, having a nested ifs is redundant, and you can go with the first version.
For the first example, if pieceisnotonedge returns false, will it also check the next condition?
No. It will "short-circuit" because if the first condition is false, checking the conditions after it is unnecessary. Read more here and here.
This is guranteed by the C++ standard:
7.6.14
... && guarantees left-to-right evaluation: the second operand is not evaluated if the first operand is false.
Note that, for || this is opposite, that is, if the first condition is "true", then checking the conditions afterwards is unnecessary
Shall i use; or...
Both are same, if you have a short if statement (with only two conditions), I would suggest using the first approach. In terms of efficiency there is no difference and you can verify this by looking at the generated assembly for both cases on godbolt
For the shown code there is no difference, both board[row+1][col] == 0 are only evaluated if pieceisnotonedge is true.
If you should use one or the other, cannot be said be in general, as it depends on other factors (like semantic, readability, …) too.
If you e.g. want to have an action that it done if either pieceisnotonedge or board[row+1][col] == 0 is false, then you probably would use &&, because then you can write:
if (pieceisnotonedge && board[row+1][col] == 0) {
} else {
// do something else
}
with your other style you would need to write:
if (pieceisnotonedge){
if (board[row+1][col] == 0) {
// do something else
}
} else {
// do something else
}
In general, your first aim should be to have readable code. While pieceisnotonedge && board[row+1][col] == 0 easy to read, more complex expressions might not be. So you would decide that on a case by case basis, if you want to use one expression or multiple if.
For the first example, if pieceisnotonedge returns false, will it also check the next condition?
No. It will stop immediately after pieceisnotonedge is evaluated to false. There is no subsequent check for the remainder condition board[row+1][col] == 0
You can use nested if as the second code as well - no difference. It's just a matter of what code would look clearer.
Our teacher for our introductory C++ course was speaking on the nature of for loops and how everything within the parentheses can be empty as long as the semicolons are there. My question is, if I were to take two for loops, one after the other, that have the same variable involved in their update statements, is it consistent across all compilers that, once the first for loop is exited, the second will just pick up the value of the variable that came about from the first loop if you keep the initial statement of the second loop empty? Our teacher was uncertain as to whether this interaction was compiler-specific; it worked in VS2017, but she expressed doubt as to whether it would work in earlier versions.
If your variable is part of the first for loop:
for(int x = 0; 10 > x; ++x)
{
}
for(; 20 > x; ++x)
{
}
then per the standard 'x' is not even defined for the second loop and the code will not compile. Note that some older compilers don't follow the standard on this point and will behave as in the next example.
If the variable is defined outside the first for loop:
int x = 0;
for(; 10 > x; ++x)
{
}
for(; 20 > x; ++x)
{
}
then when the second loop is entered 'x' will have the value it had at the time the first loop ended. In no case will 'x' be re-initialized by the second loop, or have some otherwise random value. It will either have the value obtained at the end of the first loop or result in a compilation error.
I was always under the impression that a variable declared in any kind of loop statement is scoped to that statement alone. And a little poking around in similar questions seems to confirm this idea. So I am puzzled by the following excerpt from Stroustrup's A Tour of C++ (§4.2.3 Initializing Containers p. 38):
"The push_back() is useful for input of arbitrary numbers of elements. For example:
Vector read(istream& is) {
Vector v;
for (double d; is>>d;) // read floating-point values into d
v.push_back(d); // add d to v
return v;
}
The input loop is terminated by an end-of-file or a formatting error. Until that happens, each number
read is added to the Vector so that at the end, v’s size is the number of elements read. I used a for-statement rather than the more conventional while-statement to keep the scope of d limited to the loop."
This seems to imply that variables declared in the condition of a while statement persist outside the statement body.
Let's examine that loop:
for (double d; is>>d;) // read floating-point values into d
v.push_back(d); // add d to v
Here we have:
a declaration of d
a loop condition
an empty "do on each iteration" expression
And, yes, d is limited in scope to the for loop.
Now try writing a while loop to do the same job, keeping d limited in scope. You won't be able to, because there's no place to put a declaration in the preamble of a while. Only for has that feature. A while only has a condition.
That doesn't mean the scoping rules are different for while; it only means that it is not possible to write this code using while. There aren't any "variables declared in the condition of a while statement".
[..] that variables declared in the condition of a while statement [..]
That's not possible.
Using a for statement allows to declare a variable like this
for(int a = 0; a < 5; a++) {
// Use a
}
// a is not visible anymore
If you use a while loop, it is visible
int a = 0;
while(a < 5) {
// Use a
a++;
}
// a still visible
At the moment I´m testing around with particles and have one important question.
if (condition a || condition b || condition c)
or
if(condition a)
if(condition b)
if(condition c){
}
Which is faster?
C++ uses what is known as short-circuit expression evaluation, which means that as soon as it encounters a term which determines the final result of the expression, (regardless of what the remaining terms may evaluate to,) it will stop evaluating terms.
Since TRUE OR X is TRUE regardless of the value of X, C++ will not bother evaluating X.
However, your cascaded if statement is not equivalent to the first expression. It is equivalent to an expression with multiple ANDs not multiple ORs.
This has likely been answered somewhere else before, but C++ uses the short circuit method, that is, if any condition passes, the rest are ignored (in the case of logical or: |).
The reverse is true for logical and: & - the first condition that fails short circuits the if statement and it exits early.
Here's an example:
if (condition a || condition b || condition c) {
// This code will execute if condition a is true, condition a or b is true, or if all three are true
}
if (condition a && condition b && condition c) {
// This code will only execute if all three are true, but if a is false, it will exit early, the same can be said for b
}
I would like to increment two variables in a for-loop condition instead of one.
So something like:
for (int i = 0; i != 5; ++i and ++j)
do_something(i, j);
What is the syntax for this?
A common idiom is to use the comma operator which evaluates both operands, and returns the second operand. Thus:
for(int i = 0; i != 5; ++i,++j)
do_something(i,j);
But is it really a comma operator?
Now having wrote that, a commenter suggested it was actually some special syntactic sugar in the for statement, and not a comma operator at all. I checked that in GCC as follows:
int i=0;
int a=5;
int x=0;
for(i; i<5; x=i++,a++){
printf("i=%d a=%d x=%d\n",i,a,x);
}
I was expecting x to pick up the original value of a, so it should have displayed 5,6,7.. for x. What I got was this
i=0 a=5 x=0
i=1 a=6 x=0
i=2 a=7 x=1
i=3 a=8 x=2
i=4 a=9 x=3
However, if I bracketed the expression to force the parser into really seeing a comma operator, I get this
int main(){
int i=0;
int a=5;
int x=0;
for(i=0; i<5; x=(i++,a++)){
printf("i=%d a=%d x=%d\n",i,a,x);
}
}
i=0 a=5 x=0
i=1 a=6 x=5
i=2 a=7 x=6
i=3 a=8 x=7
i=4 a=9 x=8
Initially I thought that this showed it wasn't behaving as a comma operator at all, but as it turns out, this is simply a precedence issue - the comma operator has the lowest possible precedence, so the expression x=i++,a++ is effectively parsed as (x=i++),a++
Thanks for all the comments, it was an interesting learning experience, and I've been using C for many years!
Try this
for(int i = 0; i != 5; ++i, ++j)
do_something(i,j);
Try not to do it!
From http://www.research.att.com/~bs/JSF-AV-rules.pdf:
AV Rule 199
The increment expression in a for loop will perform no action other than to change a single
loop parameter to the next value for the loop.
Rationale: Readability.
for (int i = 0; i != 5; ++i, ++j)
do_something(i, j);
I came here to remind myself how to code a second index into the increment clause of a FOR loop, which I knew could be done mainly from observing it in a sample that I incorporated into another project, that written in C++.
Today, I am working in C#, but I felt sure that it would obey the same rules in this regard, since the FOR statement is one of the oldest control structures in all of programming. Thankfully, I had recently spent several days precisely documenting the behavior of a FOR loop in one of my older C programs, and I quickly realized that those studies held lessons that applied to today's C# problem, in particular to the behavior of the second index variable.
For the unwary, following is a summary of my observations. Everything I saw happening today, by carefully observing variables in the Locals window, confirmed my expectation that a C# FOR statement behaves exactly like a C or C++ FOR statement.
The first time a FOR loop executes, the increment clause (the 3rd of its three) is skipped. In Visual C and C++, the increment is generated as three machine instructions in the middle of the block that implements the loop, so that the initial pass runs the initialization code once only, then jumps over the increment block to execute the termination test. This implements the feature that a FOR loop executes zero or more times, depending on the state of its index and limit variables.
If the body of the loop executes, its last statement is a jump to the first of the three increment instructions that were skipped by the first iteration. After these execute, control falls naturally into the limit test code that implements the middle clause. The outcome of that test determines whether the body of the FOR loop executes, or whether control transfers to the next instruction past the jump at the bottom of its scope.
Since control transfers from the bottom of the FOR loop block to the increment block, the index variable is incremented before the test is executed. Not only does this behavior explain why you must code your limit clauses the way you learned, but it affects any secondary increment that you add, via the comma operator, because it becomes part of the third clause. Hence, it is not changed on the first iteration, but it is on the last iteration, which never executes the body.
If either of your index variables remains in scope when the loop ends, their value will be one higher than the threshold that stops the loop, in the case of the true index variable. Likewise, if, for example, the second variable is initialized to zero before the loop is entered, its value at the end will be the iteration count, assuming that it is an increment (++), not a decrement, and that nothing in the body of the loop changes its value.
I agree with squelart. Incrementing two variables is bug prone, especially if you only test for one of them.
This is the readable way to do this:
int j = 0;
for(int i = 0; i < 5; ++i) {
do_something(i, j);
++j;
}
For loops are meant for cases where your loop runs on one increasing/decreasing variable. For any other variable, change it in the loop.
If you need j to be tied to i, why not leave the original variable as is and add i?
for(int i = 0; i < 5; ++i) {
do_something(i,a+i);
}
If your logic is more complex (for example, you need to actually monitor more than one variable), I'd use a while loop.
int main(){
int i=0;
int a=0;
for(i;i<5;i++,a++){
printf("%d %d\n",a,i);
}
}
Use Maths. If the two operations mathematically depend on the loop iteration, why not do the math?
int i, j;//That have some meaningful values in them?
for( int counter = 0; counter < count_max; ++counter )
do_something (counter+i, counter+j);
Or, more specifically referring to the OP's example:
for(int i = 0; i != 5; ++i)
do_something(i, j+i);
Especially if you're passing into a function by value, then you should get something that does exactly what you want.