Another 1.8.3 compiler culbit

Us I understand, pre-compiler it is really a "sequencer" , which will schedule what it is take and what is not dependent what is define and how it is define.

For example

/* Example ONE */

#define BuzzerOn
#define BuzzerOff

uint8_t aaa = 10;
uint8_t bbb = 200;

byte i = 0;

void setup() {
  for (i=0; i<aaa; i++) {
    test();
  }
}
void loop() {}
void test() {}

In this example, FOR will do 10 times. Clear.

If for instance, need to add a pre-compiler statement and change only FOR statement:

/* Example TWO */

#define BuzzerOn

uint8_t aaa = 10;
uint8_t bbb = 200;

byte i = 0;

void setup() {

#if defined (BuzzerOn)
  for (i=0; i<aaa; i++) {
#else
  for (i=0; i<bbb; i++) {
#endif

    test();
  }
}
void loop() {}
void test() {}

For this example pre-compiler doing fine, and produce code successfully.

But if do comment first FOR, pre-compiler could not find "test()" sub:

/* Example THREE */

#define BuzzerOn

uint8_t aaa = 10;
uint8_t bbb = 200;

byte i = 0;

void setup() {

#if defined (BuzzerOn)
//  for (i=0; i<aaa; i++) {
#else
  for (i=0; i<bbb; i++) {
#endif

    test();
  }
}
void loop() {}
void test() {}

At same time, if you comment a second only, pre-compiler do not detect and process successfully.

I doing something wrong ? Or there is trick I am not aware ?

Thank you my colleagues.

AssemblerMan:
Us I understand, pre-compiler

The correct term is preprocessor.

AssemblerMan:
it is really a "sequencer"

I don't think that word fits at all. In fact I think preprocessor is pretty much says it all. The preprocessor processes the code before (pre) the compiler.

AssemblerMan:
If for instance, need to add a pre-compiler statement and change only FOR statement:

You should only ever use the preprocessor when there is not other reasonable option. It makes your code much more difficult to read and debug. In this case there is no need to use the preprocessor.

AssemblerMan:
But if do comment first FOR, pre-compiler could not find "test()" sub:

/* Example THREE */

#define BuzzerOn

uint8_t aaa = 10;
uint8_t bbb = 200;

byte i = 0;

void setup() {

#if defined (BuzzerOn)
//  for (i=0; i<aaa; i++) {
#else
 for (i=0; i<bbb; i++) {
#endif

test();
 }
}
void loop() {}
void test() {}

Here we have an example of how the use of the preprocessor can make the code difficult to understand and debug. If you remove all the unnecessary complication from the sketch, the exact equivalent code is:

/* Example THREE */

uint8_t aaa = 10;
uint8_t bbb = 200;

byte i = 0;

void setup() {
//  for (i=0; i<aaa; i++) {
    test();
  }
}
void loop() {}
void test() {}

Now the problem is clear. You have an extra closing brace at the end of setup, thus the error. A good way to spot problems like this is to use the Arduino IDE's Tools > Auto Format and then check whether the automatic indentation matches your intended program structure.

When you do need to use the preprocessor conditional directives in this way you should avoid causing unbalanced brackets by writing your code like this:

void setup() {
#if defined (BuzzerOn)
  for (i=0; i<aaa; i++)
#else
  for (i=0; i<bbb; i++)
#endif
  {
    test();
  }
}

The pre-processor does literally nothing more than cut-and-paste on your source code. In your second example, your set() function:

void setup() {

#if defined (BuzzerOn)
//  for (i=0; i<aaa; i++) {
#else
  for (i=0; i<bbb; i++) {
#endif

    test();
  }
}

AFTER being run through the pre-processor, becomes this:

void setup() {






    test();
  }
}

which is NOT valid c code, as you have an extra closing curly bracket.

Regards,
Ray L.

Wow, it is so simple.
Got it, Thank you.

I need to use preprocessor commands, since my original code is optimized for the low memory and I try to save as much as I can on each corner.

Thank both of you again !
Best

The compiler is pretty smart about optimizing out anything that's not used. Your use of the preprocessor might not be as necessary for this purpose as you think.

This is correct argument , however, since the preprocessor see commented line which hides the opening bracket of the for loop then the compiler will see the incomplete for loop construct and should produce an error.

If it does not than it is indeed a compiler problem.
Smart optimization? I hope not!

I am not sure why comments are being made not to use preprocessor in this fashion.
Just take a look at some more "universal Arduino libraries". Their #ifdef ... #endif structure can get wild.

Yes, KISS is best, but if the task can be done using preprocessor , why not?

232:
since the preprocessor see commented line

The preprocessor only sees preprocessor directives, not comments.

232:
the compiler will see the incomplete for loop construct

There is no for loop. There is only a comment.

232:
and should produce an error.

If it does not than it is indeed a compiler problem.

Clearly it did produce an error.

232:
I am not sure why comments are being made not to use preprocessor in this fashion.
Just take a look at some more "universal Arduino libraries". Their #ifdef ... #endif structure can get wild.

There are things you can only do with the preprocessor. That is when it's appropriate to use it and it is an extremely useful tool in these cases. One common usage in the Arduino world is to provide support for multiple architectures or individual parts. For example:

#if defined(AVR)
//AVR specific code here
#elif defined(ESP8266)
//ESP8266 architecture specific code here
#else
#error The architecture of the selected board is not supported by this library
#endif

There are also libraries that unnecessarily use the preprocessor and are a nightmare to understand, especially when they start using lots of macro functions. Just because someone else did something does not indicate you should do it too.

One common misconception people have is that they should use #define for constants. In C++ we have something much better: The const keyword. This allows you to use regular variables in a safe way with type checking and no additional overhead.

232:
if the task can be done using preprocessor , why not?

Because, as I already said, it makes the code less readable and more difficult to debug.