Error when using #if or #ifdef

Dear all,

I try to make a sketch in which you can use a variety of display's to do the same task. I try to do this with a #define LCD_TYPE and place all the code between #if (LCD_TYPE == 1) and #endif for all the number of display's. At first this seemed to work just fine. I had #define LCD_TYPE 1 and designed the whole sketch for the first display at hand. Then I tried to move to the second LCD type and canged to #define LCD_TYPE 2 and made code in blocks with #if (LCD_TYPE == 2) #endif. But then I got weird error messages.

speedometer.ino: In function 'void setup()':
speedometer.ino:88:14: error: 'displayInit' was not declared in this scope
speedometer.ino: In function 'void loop()':
speedometer.ino:117:16: error: 'checkInput' was not declared in this scope
speedometer.ino:118:42: error: 'calcSpeed' was not declared in this scope
speedometer.ino:119:21: error: 'displaySpeed' was not declared in this scope
speedometer.ino:141:16: error: 'displayBusy' was not declared in this scope
speedometer.ino:144:16: error: 'displayIdle' was not declared in this scope
speedometer.ino: In function 'bool checkInput()':
speedometer.ino:165:11: error: 'class Adafruit_7segment' has no member named 'setCursor'
'displayInit' was not declared in this scope

At first I thought I did something wrong with an #endif or something. But if I changed back to the firt LCD everything was fine again. So I started a new sketch:

#define TEST 1

#if (TEST == 1)
  byte varname = 1;
#endif

#if (TEST == 2) 
  byte varname = 3;
#endif

void setup() {
  
  delay(2000);
  Serial.begin(9600);
  Serial.println(varname);
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

If I run this I get a 1 at the serial monitor as expected. But if I change it to #define TEST 2 I get a compile error!

deftest.ino:12:3: error: 'byte' does not name a type
deftest.ino: In function 'void setup()':
deftest.ino:17:13: error: 'delay' was not declared in this scope
deftest.ino:18:3: error: 'Serial' was not declared in this scope
deftest.ino:19:18: error: 'varname' was not declared in this scope
'byte' does not name a type

Huh?? Why? And the line number in the error is off by 4 (line 12 is blank, it's line 8 in the sketch).

So I thought, mayby I can't check the value. So I edited to use #ifdef

#define TEST_A
//#define TEST_B


#ifdef TEST_A
  byte varname = 1;
#endif

#ifdef TEST_B
  byte varname = 3;
#endif

void setup() {
  
  delay(2000);
  Serial.begin(9600);
  Serial.println(varname);
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

And again, I get a 1 in serial monitor. But if I change to //#define TEST_A

define TEST_B

deftest.ino:14:3: error: 'byte' does not name a type
deftest.ino: In function 'void setup()':
deftest.ino:19:13: error: 'delay' was not declared in this scope
deftest.ino:20:3: error: 'Serial' was not declared in this scope
deftest.ino:21:18: error: 'varname' was not declared in this scope
'byte' does not name a type

Hello again error!

Does anyone why it fails? I think it should just leave out a part of the code and compile the rest.

septillion: Does anyone why it fails? I think it should just leave out a part of the code and compile the rest.

Remove the brackets in the comparison:

#define TEST 1

#if TEST == 1
  byte varname = 1;
#endif

#if TEST == 2
  byte varname = 3;
#endif

Does anyone why it fails? I think it should just leave out a part of the code and compile the rest.

The IDE modifies your code when it creates a cpp file for the compiler to compile. Using #if, #ifdef, #endif, etc. confuses it as to WHERE to make the modifications.

Usually adding something like

byte me;

as the first line of the sketch solves the problem.

Modifying my code when making the cpp, that's indeed the idea. Adding byte me; indeed fixes the problem! :o But why? Why does it fix it and why get's the compiler confused?

Why does it fix it and why get's the compiler confused?

The compiler isn't confused. The IDE is. It doesn't understand postprocessor directives. It assumes that the # is going to be followed by the word include.

So, what happens is that the IDE adds the #include statement to include Arduino.h, where byte and things like that are defined, after the first non-# statement in the code. In your case, that happens to be in the middle of a #if/#endif block that does not get compiled.

Adding a non-# statement at the top of the code gives the IDE a different (and correct) insertion point.

Thnx Paul! Explains it :D But I really hope they fix it in the future.