Switch/case style

Processor = WOKWI

The snippet below, part of a class, functions as desired without a default case and without an ending break.  I conclude then that the compiler secretly adds these things (or their equivalents) anyway even though I didn't.  If that's true there would be no advantage in memory use or execution time by omitting these things.  Does this sound right?

I get that it may seem a little awkward and is probably bad form.

switch (_flashState) {

          case begin_T1_time:
            digitalWrite(_PIN_TO_FLASH, _IS_OUTPUT_INVERTED ^ 0x01);
            _timerAcc = millis(); // Reset the timer
            _flashState = dwell_T1_time;
            [[fallthrough]];

          case dwell_T1_time:

            if (millis() - _timerAcc < _T1_Preset)
              break;
            [[fallthrough]];

            // Begin_T2_time:

            digitalWrite(_PIN_TO_FLASH, _IS_OUTPUT_INVERTED ^ 0x00);
            _timerAcc = millis(); // Reset the timer
            _flashState = dwell_T2_time;
            [[fallthrough]];

          case dwell_T2_time:

            if (millis() - _timerAcc < _T2_Preset)
              break;
            // _flashState = begin_T1_time;
            // break;
            // default:

            _flashState = begin_T1_time;

        } // End of switch

They are not added, the code runs as expected.

A "break" is the same result as a "break" in a for-statement or a while-statement. It breaks out of the switch-case. It is optional for the switch-case-statement (optional everywhere).
The "default" in the switch-case is also optional.

You are used to a certain way the switch-case is used and the compiler might give warnings when it is used otherwise. But there are not many rules for the switch-case, you can almost do whatever you want. Your code is not bad, it is okay.
It is, for example, allowed to put the "break" somewhere deep in layers of if-statements, or the "default" at the top.

Removing the ending "break" should not make any difference.
The "default" can be omitted when not needed.

I think there is a underlying problem. You should write source code that is easy to read and to maintain. The "default" can be handy to capture an unwanted value, to avoid that a bug causes a avalanche of problems. Let the compiler take care of the generated binary code.
You should not try to be smart and make ugly code.

How did you conclude this?

Because it doesn't act broken.

I wasn't inclined to leave it that way I was just playing around with trying to make it shorter and possibly more efficient and was mildly surprised when it still worked.

Another thing, I didn't click the 'solved' button so how come there's a check in the solution box?

That's for you to click you muppet if you think the answer given is the solution to your post... no one else sees that. :laughing:

But where did the idea that default was added came from?

I assumed it was necessary and the compiler was somehow invisibly adding it (or including something that gives the same effect) by itself.  I've been disabused of that notion since learning that break and default are optional.

Ah Ok - got it

I cleaned up a few things and this is the current state of the sketch:

What would you suggest to move to whatever is above 'okay' ?

I don’t get the purpose of the fallthrough, say you enter with begin_T1_time you intialize _timerAcc And change the state.., so going to the next case has no effect at that point in time the delta time will be zero so you’ll break anyway…

Seems complicated for a simple blink to me

As I wrote before: "You should not try to be smart and make ugly code", so in my world, this single line has three severe bugs:

if (_enabled ^ _IS_INPUT_INVERTED) {

The two 'bool' variables are used as bits, the 'xor' operates on those bits and the result of the 'xor' is converted into 'bool' for the condition of the if-statement.

The same here:

digitalWrite(_PIN_TO_FLASH, _IS_OUTPUT_INVERTED ^ false);

The digitalWrite() does also not take a 'bool' variable as its second parameter. It can be HIGH or LOW.

The fallthrough was in lieu of the comment "fallthrough is deliberate".  What I've read recommends one or the other after a case so that humans understand the lack of a break and [[fallthrough]] tells the compiler there's no need for a warning message.

So like:

if (_enabled != _IS_INPUT_INVERTED) {

?

Yes

Thanks.

And I substituted:

 digitalWrite(_PIN_TO_FLASH, (_IS_OUTPUT_INVERTED ? LOW : HIGH));

for

digitalWrite(_PIN_TO_FLASH, _IS_OUTPUT_INVERTED ^ false);

Is this more along the lines you were thinking?

Yes :smiley:

Thanks for the advice! :bowing_man:t4:

I got that, my point was that there is no need to fall through. You could just break