Where to declare and initialize variables


Mostly, you are advised to declare variables only shortly before first usage, meaning: as late as possible.
Actually, when you try to set the value of a variable to the return value of a function it just won't work.
Have a look at this example:

/*
 usage of US distance sensor HC-SR04
 */
#define DECLARE_EARLY

const byte trigger = 6;
const byte echo    = 5;

#ifdef DECLARE_EARLY
float oldValue;
#endif

void setup() {
  Serial.begin(9600);
  Serial.println("Hello");
  pinMode(trigger, OUTPUT);
  pinMode(echo, INPUT);

#ifdef DECLARE_EARLY
  oldValue = getDistance();
#endif
}

#ifndef DECLARE_EARLY
// declare as late as possible
float oldValue = getDistance();
#endif

void loop() {
  float newValue = getDistance();
  // print mean to smooth values 
  Serial.println( (newValue + oldValue) / 2);
  oldValue = newValue;
}

float getDistance() {
  digitalWrite(trigger, HIGH);
  delay(1);
  digitalWrite(trigger, LOW);
  float duration = pulseIn(echo, HIGH) * 1E-6;
  const int c = 340; // speed of sound
  return (duration / 2) * c;
}

If you do not define DECLARE_EARLY the variable oldValue will get declared and initialized immediately before its first usage, and the compiler is happy with it.

But inspite of the fact that this declaration is found after the setup function it will be executed before.
And the bad news is: the functions delay() and pulseIn() cannot be called at this early time.


Let's have a look at another example. There are six variables, called t1 to t6, getting their values one after the other. Or not?
Check the results ...

/*
  Visibility of function prototypes and declarations
  Obviously, t3 and t4 are getting their values before t2!
*/
// forward references needed:
long func1();
bool func2();

long magic = 1234;
long t1 = ++magic;
long t2;
long t3;
long t4 = func1();
long t5;
bool dummy = func2();

void setup() {
  Serial.begin(9600);
  Serial.println(__FILE__);
  Serial.println(dummy); // force to evaluate func2
  t2 = ++magic;
}

long t6 = ++magic;

void loop() {
  Serial.print("t1 = "); Serial.println(t1);
  Serial.print("t2 = "); Serial.println(t2);
  Serial.print("t3 = "); Serial.println(t3);
  Serial.print("t4 = "); Serial.println(t4);
  Serial.print("t5 = "); Serial.println(t5);
  Serial.print("t6 = "); Serial.println(t6);
  while (true);
}

// both functions have a side effects!
long func1() {
  t5 = ++magic;
  return ++magic;
}

bool func2() {
  t3 = ++magic;
  /*
    better not call functions at this time!
    delay(1);
  */
  return false;
}

Lessons we learned:

The results of the lexical analysis of the compiler does not say much about the way your code will be executed.


contact: nji(at)gmx.de