function calls to initialize variables outside setup() and loop()

The following code works, but only if the code for "func()" is placed before setup() and loop(). If "func()" follows setup and loop, I get "func was not declared in this scope".

I'm using Arduino 1.8.2

I've tried to discover what rules might govern what the compiler do might in such cases, but so far have come up with a blank. Discussion encouraged!

int func(void) {
  return 11;
}

int x = func();

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.print("x ");
  Serial.println(x);  //prints 11
}

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

}

How are you compiling your code? The IDE creates function prototypes for most functions. Other editors/systems do not.

If you define the function prototype, before you reference the function, you can put your function anywhere.

I simply use the IDE to compile and upload, which I admit is mysterious in how it handles placement of function prototypes.

The real question is why this function call ever works, since func() is not called from main(), setup() or loop()!

Because the compiler is smart. It can see that the function is so small that it can be inlined. Then it sees that it is a constant expression known at compile time. So it just puts that constant in x. There is no function call by the time that the linker is looking for functions and function prototypes.

This is an edge case that the Arduino IDE doesn't handle properly with the magic function prototypes.

Hi,

The usual workaround as I understand it is to add the function prototype yourself to a .h file which you then #include in your .ino file.

Hardly seems worth it in this case though.

best,
Michael

mjward:
The usual workaround as I understand it is to add the function prototype yourself to a .h file which you then #include in your .ino file.

It's not necessary to put it in a .h file if you don't want. This works fine:

int func(void);

int x = func();

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.print("x ");
  Serial.println(x);  //prints 11
}

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

int func(void) {
  return 11;
}