Syntax question (if/else-{}{}) to C/C++ experts

Since nearly 40 years I am programming in "C", later in "C++", and since a lot of years I do not need references for the language any more.
But yesterday I detected a mistake in my program, which I did not expect. I doubt, whether it is a syntax error I make, or the compiler (arduinoPlugin/packages/arduino/tools/arm-none-eabi-gcc/7-2017q4/bin/arm-none-eabi-g++) is not working correct.

It is a very simple routine:

if(i > 0)
  a = true;
else
  b = true;

As expected, setting i to 0 before makes b true. The same behavior (as expected) with

if(i > 0)
{
  a = true;
}
else
{
  b = true;
}

But mixing brackets and non brackets with

if(i > 0)
{
  a = true;
}
else
  b = true;

is not setting b to true.
(This routine is contained in a library/class and b is public and tested with another program.)
And this I do not understand.
Are my thousands of programmed C code lines before simply without such an error and did I make this error the first time in my life?
Or is it an error of the compiler, because my understanding of using brackets in such routines is: You need brackets to aggregate multiple lines/statements handled like one statement. If there is only one statement/line, there is no need for brackets.

Does someone know the circumstances of using brackets in this case and can give me a hint?

This (your claim) is not true.

bool a, b;

void setup() {
  Serial.begin(115200);
  for (int i = 0; i < 2; i++) {
    a = false;
    b = false;
    if (i > 0) {
      a = true;
    } else
      b = true;
    Serial.print(F("i = "));
    Serial.print(i);
    Serial.print(F(", a = "));
    Serial.print(a);
    Serial.print(F(", b = "));
    Serial.println(b);
  }
}
void loop() {}
i = 0, a = 0, b = 1
i = 1, a = 1, b = 0

Hello
I can´t replay your issue by using this test sketch:

int i=0;
  if (i > 0)
  {
    Serial.println("a=true");
  }
  else
    Serial.println("b=true");

  i = 1;
  if (i > 0)
  {
    Serial.println("a=true");
  }
  else
    Serial.println("b=true");
b=true
a=true

Have a nice day and enjoy coding.

Thank you very much (both).
Meanwhile I tested the routine in different levels and it is as You found out, that there is no need for the extra brackets.
My routine with the error is located very deep in a switch-statement inside a public method of a class.
Because I have no errors when I implement the extra brackets, I think the problem is with the compiler at this level of coding.

Have a nice day too (@Whandall & @paulpaulson) and thanks again.

I doubt that also. It is probably your mistake that you don't see (nor show).
But having brackets always is better IMHO anyway.

1 Like

The combination of switch-case and brackets can do that, but only if you put a bug in it :bug:

The switch-case can not have local variables in a 'case', but it can if brackets are used. So if you declare a local variable with the same name as a already existing variable then the behavior of the compiler might change with brackets.
If you use (bad) macros, they might cause this as well.

@profrob, please show us a sketch that shows the problem. Tell which Arduino IDE is used and which Arduino board. If you can not prove your claim, then it does not exist :woozy_face:

The value of i is undefined

thanks for your notice.

warning: 'i' is used uninitialized in this function [-Wuninitialized]

@Koepel and all

I wanted to be sure, that the syntax in if/else with mixed brackets and non brackets is OK. And the answers are very helpful and confirm the correctness.
But it may be, that the error comes from a wrong usage in the context.
Here is the routine, where the error occurs:

void SensorLSM9DS1::run()
{
  switch(runState)
  {
    case rsInit:
      runState = rsScanAGReq;
      break;

      // ------------ Accel & Gyro ------------

    case rsScanAGReq:
      twPtr->recByteReg(AG_Adr, AG_Status, &twiByte);
      runState = rsScanAGChk;
      break;

    case rsScanAGChk:
      if(twiByte.twiStatus != TwStFin)
        break;
      if((twiByte.value & 0x03) == 0)
      {
        runState = rsScanMReq;    // -> Magnet
        break;
      }

      twiByteSeq.len = 12;
      twPtr->recByteRegSeq(AG_Adr, G_Out, &twiByteSeq);
      runState = rsFetchAG;
      break;

    case rsFetchAG:
      if(twiByteSeq.twiStatus != TwStFin)
        break;

      for(int i = 0; i < 12; i++)
        rawDataAG.byteArray[i] = byteArray[i];

      if(avgSetAG > 0)
      { // ----------------------------------------------------
        sumA.x += rawDataAG.valueAG.A.x;
        sumA.y += rawDataAG.valueAG.A.y;
        sumA.z += rawDataAG.valueAG.A.z;
        sumG.x += rawDataAG.valueAG.G.x;
        sumG.y += rawDataAG.valueAG.G.y;
        sumG.z += rawDataAG.valueAG.G.z;
        avgCntAG--;

        if(avgCntAG == 0)
        {
          rawDataAG.valueAG.A.x = sumA.x / avgSetAG;
          rawDataAG.valueAG.A.y = sumA.y / avgSetAG;
          rawDataAG.valueAG.A.z = sumA.z / avgSetAG;
          rawDataAG.valueAG.G.x = sumG.x / avgSetAG;
          rawDataAG.valueAG.G.y = sumG.y / avgSetAG;
          rawDataAG.valueAG.G.z = sumG.z / avgSetAG;
          sumA.x = sumA.y = sumA.z = sumG.x = sumG.y = sumG.z = 0;
          avgCntAG = avgSetAG;
          newValueAG = true;
        }
      } // ----------------------------------------------------
      else
      { ***************************
        newValueAG = true;
      } ***************************

      runState = rsScanAGReq;
      break;

      // ------------ Magnet ------------

    case rsScanMReq:
      twPtr->recByteReg(M_Adr, M_Status, &twiByte);
      runState = rsScanMChk;
      break;

    case rsScanMChk:
      if(twiByte.twiStatus != TwStFin)
        break;
      if((twiByte.value & 0x08) == 0)
      {
        runState = rsScanAGReq;    // -> Accel,Gyro
        break;
      }

      twiByteSeq.len = 6;
      twPtr->recByteRegSeq(M_Adr, M_Out, &twiByteSeq);
      runState = rsFetchM;
      break;

    case rsFetchM:
      if(twiByteSeq.twiStatus != TwStFin)
        break;

      for(int i = 0; i < 6; i++)
        valueArrayM[i] = byteArray[i];
      newValueM = true;
      runState = rsScanAGReq;
      break;
  }
}

Do not think about the creating of the average of measurements, it is the first draft of the routine and not tested. Till now I only tested with avgSetAG = 0 and detected that problem with or without the brackets (marked with asterisks).
I do not use local variables of the run-function, all variables are declared with the class.
Without the brackets I do not get values because the application is waiting for newValueAG == true. With the brackets it works as expected.
I mentioned the compiler at the beginning of the thread.
My IDE is Eclipse/Sloeber and the Board is Arduino Nano BLE 33.

Thank You for Your interest and help.
The sketch (application) itself is rather big and using more libraries. It shows the measurement values formatted on a serial terminal to check the moving of the Arduino board.

what compiler are you using? Also you set


newValueAG = true;

in both scopes, how do you know which one of them sets it?

Haha, good catch, this is what wasn’t working in the real code…

a7

For those of You, who thought about the averaging in that routine:
Meanwhile it is tested (OK), I added the reset (=0) of the sum values in the listing above. The initialization of averaging is done by avgSetAG = avgCntAG = number of values.

For those of You, who did not recognize the two different if-levels, I added two comment lines //---- after the coupling brackets.

The application synchronizes to newValueAG == true. So with number 10 in avgSetAG, the output to the terminal is simply 10 times slower.

Thank Yo all again for the discussion.

If you're so convinced of that, post a COMPLETE MRE that compiles, demonstrates the error, and that everyone here can compile and test.

Finally I found the error.
It is my mistake.
For controlling the TWI communication to fetch sensor data I used the same variable as for observing sensor status. But that is wrong, because I hand over different variables for the two TWI procedures.
What happened is, that the discussed if-sequence (data fetch state) was only reached randomly.
That this was synchronous to my changes of using brackets or not with recompiling and testing, is another random matter.
It is like a series of changing red and black with roulette.

After repairing the TWI check, everything works fine and I can use the mixture of brackets and non brackets as we all expected.
And of course the compiler is working correct.

So I thank you all again for the discussion which helped me to continue searching the error.

1 Like