0

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.

JeJo
  • 30,635
  • 6
  • 49
  • 88
  • The answer to this question depends on the AND operator. Is it a built-in operator or a user-defined overload? The behavior is different. – Thomas Sablik Aug 09 '20 at 06:33
  • 1
    This doesn't address the question, but for pawn moves you don't have to check `row + 1`. A pawn can never be on the 8th rank; `row + 1` is always valid. – Pete Becker Aug 09 '20 at 13:42
  • Yes, you are absolutely right. Number one: Starting stages of the game so i did not add pawn promotion. number two was it also applies to a column. That is if a pawn is on the horizontal edge i dont need to check if board[row+1][col+1] if a piece is present. And the same rule applies for all the pieces. –  Aug 09 '20 at 14:34

4 Answers4

5

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.

JeJo
  • 30,635
  • 6
  • 49
  • 88
  • 1
    Noting that this question is tagged C++, the short-circuiting by operators `&&` and `||` does not occur for user-defined overloads of `operator&&()` and `operator||()`. If such overloads are provided and called, then an expression of the form `a && b` or of `a || b` WILL evaluate both `a` and `b`, rather than short-circuiting if `a` is true. – Peter Aug 09 '20 at 06:30
  • @Peter Of course, it will. I have only emphasized the sentence, which is relevant to the question (Assuming that the OP is not overloading them). However, it is there in the citation, what I have added. One should read it completely. – JeJo Aug 09 '20 at 06:32
  • I am confused as I am new to the language, should I use it, in c++ –  Aug 09 '20 at 06:42
  • 1
    @AryanParekh Of course, you can. In C++ one can also [overload `operator&&`](https://stackoverflow.com/questions/25913237/is-there-actually-a-reason-why-overloaded-and-dont-short-circuit). Peter was mentioning that in case you [have overloaded the `operator&&`](https://en.cppreference.com/w/cpp/language/operators), in the code, the behaviour is different/ order of evaluation is not guaranteed, since it behaves like a normal function call, and will be evaluating both conditions (This is same for `operator||` overloading). I hope, you have not overloaded the `operator&&` in your code. – JeJo Aug 09 '20 at 06:46
2

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

Waqar
  • 8,558
  • 4
  • 35
  • 43
  • Thank you for this! is there any difference in its effeciency, that means, is there any difference in the time taken for both the examples, because it can perform the generator function well more than 50,000 times in my chess engine! –  Aug 09 '20 at 06:08
  • 2
    No. There will be no difference at all. The efficiency will be exactly the same – Waqar Aug 09 '20 at 06:08
  • @AryanParekh If you are in doubt, you can try both on [Compiler Explorer](https://godbolt.org/) and compare the generated assembly. Even if you do not read assembly naturally a "pessimization" will usually be quite obvious simply based on the amount of code generated. – ravnsgaard Aug 09 '20 at 07:02
2

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.

t.niese
  • 39,256
  • 9
  • 74
  • 101
1

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.

artm
  • 17,291
  • 6
  • 38
  • 54
  • not really in this case it does not matter but if you do `if (a && b && c)` then there is no guarantee it will be evaluated in order `a,b,c` and also no guarantee the execution will stop on first false ... so if conditions are not "order" safe (like array range checks) it should be nested `if`s and if the conditions are safe it can be both versions.... – Spektre Aug 09 '20 at 06:07
  • 3
    @Spektre source please? – artm Aug 09 '20 at 06:16
  • experience in past (like 10 years ago)... on MCU: GCC U-Keil and x86 BCC32 (BCB 4,5)... However newer versions might behave differently – Spektre Aug 11 '20 at 06:06