what conditional is faster

I want to know what variant from these two are faster:

if(a){
    if(b){
        //something here
    }
}

or

if(a and b){
    //something here
}

Thanks!

They will almost certainly compile to exactly the same code.

But, the more important question is: Why on earth do you care? Shaving one or two clock cycles will almost never make any difference whatsoever, and pursuing such microscopic optimizations is a complete waste of time and energy. It is exceedingly rarely that such optimization is in any way justified, and in those circumstances the better solution is to simply resort to assembly language.

Regards,
Ray L.

#2, though in the gran scheme of things it's not likely to matter much.

"Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%."

-- Donald Knuth

This probably isn't part of that 3%.

It can't be the same code because of short circuiting. For the second, if a is false b is never evaluated and the branch not taken. For the second, both if's have to be evaluated.

Thanks for responses!

Why on earth do you care?

For my curiosity! :slight_smile:
I think that is something interesting because It is met frequently.

KeithRB:
For the second, both if's have to be evaluated.

Nope. The whole construct (in this case the if) is skipped if a is false.

Ah! you are right.

I agree that putting a bunch of time and energy into optimizing before determining if it's even necessary is a bad idea but it's worth getting into some good coding habits that don't take much, if any, extra time or make the code harder to read/maintain. For example:

if (readFlag == true && analogRead(A0) > 200) {

instead of:

if (analogRead(A0) > 200 && readFlag  == true) {

Takes very little extra effort and has the potential to make a big difference in the speed of your code. There is middle ground between not considering optimization at all and going overboard.

pert:
I agree that putting a bunch of time and energy into optimizing before determining if it's even necessary is a bad idea but it's worth getting into some good coding habits that don't take much, if any, extra time or make the code harder to read/maintain. For example:

if (readFlag == true && analogRead(A0) > 200) {

instead of:

if (analogRead(A0) > 200 && readFlag  == true) {

Takes very little extra effort and has the potential to make a big difference in the speed of your code. There is middle ground between not considering optimization at all and going overboard.

I still don't really understand why

if (readFlag == true && analogRead(A0) > 200) {

is better than

if (analogRead(A0) > 200 && readFlag  == true) {

I know the coding order in C but not sure how the machine code in reallity. Can you explain more about the optimization?

They're evaluated in the order they're placed.
Evaluating this:-readFlag == truetakes very little time.

Evaluating this:-
analogRead(A0) > 200takes a little over 100us.
If the first is false, the second is not tested.

OldSteve:
They're evaluated in the order they're placed.
Evaluating this:-readFlag == truetakes very little time.

Evaluating this:-
analogRead(A0) > 200takes a little over 100us.
If the first is false, the second is not tested.

It's worth noting that this is not accidental, it's part of the definition of the C++ language. It's also true of other languages like java, where you use constructs like

if(p != null && p.value < 10)

Another spot you'll see it is in unix shell scripts: for f in * ; do thing "$f" || echo "thing $f failed"; done

Relying on the "short circuiting' behaviour of the ||, &&, and ?: operators is a common programming idiom.

vlad2005:
I want to know what variant from these two are faster:

Compile both and extract the assembly code using avr-objdump.

C:\Users\sterretje\Documents\Arduino\Projects\Forums\test>"C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avr-objdump.exe" -S sketch_sep20b.ino.elf > sketch_sep20b.ino.lst

Using IDE 1.6.7, both of your versions result in the same assembly code

void loop()
{
 13a:	cf 93       	push	r28

  byte b1 = digitalRead(2);
 13c:	82 e0       	ldi	r24, 0x02	; 2
 13e:	0e 94 14 01 	call	0x228	; 0x228 <digitalRead>
 142:	c8 2f       	mov	r28, r24
  byte b2 = digitalRead(3);
 144:	83 e0       	ldi	r24, 0x03	; 3
 146:	0e 94 14 01 	call	0x228	; 0x228 <digitalRead>

  if (b1)
 14a:	cc 23       	and	r28, r28
 14c:	49 f0       	breq	.+18     	; 0x160 <loop+0x26>
  {
    if (b2)
 14e:	88 23       	and	r24, r24
 150:	39 f0       	breq	.+14     	; 0x160 <loop+0x26>
    {
      Serial.println("Both high");
 152:	60 e0       	ldi	r22, 0x00	; 0
 154:	71 e0       	ldi	r23, 0x01	; 1
 156:	8c e2       	ldi	r24, 0x2C	; 44
 158:	91 e0       	ldi	r25, 0x01	; 1
    }
  }

}
 15a:	cf 91       	pop	r28

  if (b1)
  {
    if (b2)
    {
      Serial.println("Both high");
 15c:	0c 94 69 03 	jmp	0x6d2	; 0x6d2 <_ZN5Print7printlnEPKc>
    }
  }

}
 160:	cf 91       	pop	r28
 162:	08 95       	ret
void loop()
{
 13a:	cf 93       	push	r28

  byte b1 = digitalRead(2);
 13c:	82 e0       	ldi	r24, 0x02	; 2
 13e:	0e 94 14 01 	call	0x228	; 0x228 <digitalRead>
 142:	c8 2f       	mov	r28, r24
  byte b2 = digitalRead(3);
 144:	83 e0       	ldi	r24, 0x03	; 3
 146:	0e 94 14 01 	call	0x228	; 0x228 <digitalRead>

  if(b1 && b2)
 14a:	cc 23       	and	r28, r28
 14c:	49 f0       	breq	.+18     	; 0x160 <loop+0x26>
 14e:	88 23       	and	r24, r24
 150:	39 f0       	breq	.+14     	; 0x160 <loop+0x26>
  {
    Serial.println("Both high");
 152:	60 e0       	ldi	r22, 0x00	; 0
 154:	71 e0       	ldi	r23, 0x01	; 1
 156:	8c e2       	ldi	r24, 0x2C	; 44
 158:	91 e0       	ldi	r25, 0x01	; 1
  }
  
}
 15a:	cf 91       	pop	r28
  byte b1 = digitalRead(2);
  byte b2 = digitalRead(3);

  if(b1 && b2)
  {
    Serial.println("Both high");
 15c:	0c 94 69 03 	jmp	0x6d2	; 0x6d2 <_ZN5Print7printlnEPKc>
  }
  
}
 160:	cf 91       	pop	r28
 162:	08 95       	ret

Note
the elf files can be found in
C:\Users\yourusername\AppData\Local\Temp\buildXXX.tmp; observe the IDE's output window to see which temporary directory is used; e.g.

"C:\Program Files (x86)\Arduino\tools-builder\ctags\5.8-arduino5/ctags" -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives [b]"C:\Users\sterretje\AppData\Local\Temp\build865386780d8ee6fd36497e86b1d5bdcf.tmp\[/b]preproc\ctags_target_for_gcc_minus_e.cpp"

A rationale for using two separate if would be if you want two separate else. Otherwise indeed it generates the same code