bug in switch ?

Hi,

maybe I'm just being dumb but I'm not getting expected output from a switch statement.

  switch( line[char_counter] ) {  // leave visible trace of input
   case 'S' : {printString(line);serial_write('S');}
   case 'L' : {printString(line);serial_write('L');}
//    case 'Z' : printString(line);
 }

The char pointed to by line[char_counter] can only have one value at the time this is executed but both cases are printing. if I add the Z case I get three lines printed .

I could add a break ( which would be more efficient) but this should not be necessary.

I found a bug relating to switch on AVR dating back to 2002 but nothing about this. What am I missing?

[BTW how to post code snippets here, posting as a quotation is not the best]

ardnut:
[BTW how to post code snippets here, posting as a quotation is not the best]

Use the </> icon above the :slight_smile: and it comes out…

like this

But, snippets as opposed to whole sketches are generally frowned upon, since often the problem is actually somewhere else in the sketch, not the snippet.

ardnut: What am I missing?

break

I could add a break ( which would be more efficient) but this should not be necessary.

Why is break not necessary?

Why is break not necessary?

because if the expression in switch equals 'S' the 'L' case should not execute and vice versa.

A break would simple stop the switch even doing the test for 'L' but it should not be true.

thanks JimboZA, fixed

ardnut:
A break would simple stop the switch even doing the test for ‘L’

Are you certain? Have you tested that theory?

I don’t need to test the “theory” , a break is a jump to the end of the switch statement. Nothing after it gets executed. Since I’m not even sure that the compiler is working properly “testing” anything is not helpful.

If you are able to say that I am mistaken by referring to the spec, that may be useful.

When line[char_counter] is 'S', all of the following lines of code will run...

printString(line);
serial_write('S');
printString(line);
serial_write('L');

Is that what you want?

ardnut: Since I'm not even sure that the compiler is working properly "testing" anything is not helpful.

lol

Well, I'm sure it is working properly.

I found a bug relating to switch on AVR dating back to 2002 but nothing about this. What am I missing?

Your knowledge of C.

[quote author=Coding Badly link=msg=2309438 date=1436432673] When line[char_counter] is 'S', all of the following lines of code will run...

printString(line);
serial_write('S');
printString(line);
serial_write('L');

Is that what you want?

[/quote]

No that's what I've got and not what I intended.

[quote author=Nick Gammon link=msg=2309445 date=1436432976] lol

Well, I'm sure it is working properly.

Your knowledge of C. [/quote]

Thanks Nick. since there have been bugs in AVR-GCC switch in the past , the idea is sadly not as silly as you seem to think.

You could have been more explicit but in view of your pedigree, if you say it works I believe you.

http://embeddedgurus.com/stack-overflow/2010/04/efficient-c-tip-12-be-wary-of-switch-statements/

Having read this, I think the best thing to do is remove all use of switch in this application which is a nearly full arduino's worth of code already. [ 16b less coded as if() ]

Perhaps you can explain why the 'L' case gets executed when the switch variable is not equal to 'L'.

ardnut: Perhaps you can explain why the 'L' case gets executed when the switch variable is not equal to 'L'.

I think it's because without the break, both cases are actually OR'd, and all statements are carried out if either or both cases is true. Without the break, the two cases are evaluated at the same time; since one is true, both prints happen.

Note the "I think", though..... E&OE

What seems to happen is that the second 'case' without a break is a syntax error that fails to get reported and compiler happily carries on to the subsequent code having simply ignored it.

But if you do want to OR two cases, the correct was is to do it with no break, as explained to me a long while ago here:

switch (value) {
  case 1041:
  case 3089:
    // statements
    break;
   }

Admittedly, your case is subtly different in that you have statements after each case and mine has all the statements after both before the single break.

But I'm inclined to suggest you move past this, bung the break in and have code that works.....

Thanks Jim, so that is legit syntax. Typical of the obtuse way things are written in C. What does one do to effect an AND ? ? ? LOL

As someone once said : C offers the speed and efficiency of assembler with the readability of .... assembler. ;)

ardnut: Perhaps you can explain why the 'L' case gets executed when the switch variable is not equal to 'L'.

Without the "break" the 'S' case falls down and executes the 'L' case.

eg.

switch (foo)
  {
  case 'S':
  case 's':
     // do something
    break;
  }

It's designed like that. It's not a bug.

Thanks for the reply Nick. Jimbo covered that just above.

Totally non-intuitive to read the code , but just one of those oddities you need to learn and remember.

I've manage to gobble a few extra bytes by going straight to if () else if () structure anyway, which is a bonus.

Some of these switches were in ISRs too, so it's tightened it up a bit.

http://www.cplusplus.com/doc/tutorial/control/

almost at the end switch is explained very well