Need to initialize a variable when declaring it in a function?

Do I need to initialize a variable to "0" at the beginning of a function to avoid getting random
values?


int a; //Does not need to be Initialized to 0, correct?
int b; //Does not need to be Initialized to 0, correct?
int answer;  //Does not need to be Initialized to 0, correct?




int myMultiplyFunction(int x, int y) { // declaring a variable without initializing may get random value?
  int result;                         // declaring a variable without initializing may get random value?
  result = x * y;
  return result;
}


void setup() {
  Serial.begin(9600);
}

void loop() {

a=5;
b=2;

  answer = myMultiplyFunction(a, b);  // k now contains 6
  Serial.println(answer);
  delay(500);
}


Yes.

Are you sure?
Typical examples of functions do not have initializing values.
FuncAnatomy

such as here:

void setup() {
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
}

void loop() {
  blinkLED(9, 500);
  blinkLED(10, 1000);
}

void blinkLED(int pin, int duration) {
  digitalWrite(pin, HIGH);
  delay(duration);
  digitalWrite(pin, LOW);
  delay(duration);
}

and here

void setup(){
  Serial.begin(9600);
}

void loop() {
  int i = 2;
  int j = 3;
  int k;

  k = myMultiplyFunction(i, j); // k now contains 6
  Serial.println(k);
  delay(500);
}

int myMultiplyFunction(int x, int y){
  int result;
  result = x * y;
  return result;
}

Why didn't you initialise that?

Exactly because it was not in the Arduino.cc example. Hence my question.

I know that "static" variables have to be initialized.

But most functions that I see have no initialization ... just int x; , byte x; , etc.

And why do almost all "for loop" examples have

for (int i = 0; i <= 255; i++) {  ////////   int i IS initialized
    analogWrite(PWMpin, i);
    delay(10);
  }

and not

for (int i ; i <= 255; i++) {  ////////   int i IS initialized
    analogWrite(PWMpin, i);
    delay(10);
  }

Beats me..

Turn up compiler warnings.

If the use is like the code example, you don't have to initialise the variable in the definition.

If the first thing you did was print it, you would expect to see a random value, if you didn't initialise or assign one.

If the variable is

static int foo;

it will get an initial value just like the global did in you examlpe.

a7

...it is initialised in the very next line.

1 Like

Global variables will automatically be initialised... local variables will not (static local variables are a special case as they are more like globals).

IMO it is good practice to always initialise variables. Don't try and double guess what the compiler will do.

1 Like

Got no warnings in either example.

Even worst than getting a random value, reading an uninitialized variable will cause undefined behavior. You might get a random value, you might get the same value every time, the program may just immediately crash, it might crash at a later time. Anything can happen.
https://www.learncpp.com/cpp-tutorial/uninitialized-variables-and-undefined-behavior/

Because the compiler is smart enough to see these 2 lines...

  int result;
  result = x * y;

as...
int result = x * y;

If you did...

int myMultiplyFunction(int x, int y){
  int result;
//  result = x * y;
  return result;
}

You get...

/var/folders/4z/3g9th3gs4cng3b803dg5bhw40000gn/T/arduino_modified_sketch_285026/Blink.ino:18:10: warning: 'result' is used uninitialized in this function [-Wuninitialized]
   return result;
          ^~~~~~```

Obviously it is an error.

Exactly.

   int foo;

//   foo = 42;
   Serial.print(foo);

sketch_jan30a.ino: In function 'setup':
sketch_jan30a.ino:9:16: warning: 'foo' is used uninitialized in this function [-Wuninitialized]
Serial.print(foo);
~~~~~~~~^

Uncomment the assignment and the problem is not. You don't get a warning if you know what you are doing.

The missing initial value in the for loop generates a warning.

a7

1 Like

Here you go..

byte myFunction(byte param) {
  byte aa;
  if (digitalRead(param) == HIGH) {
    aa = 1;
  }
  return aa;
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
}

void loop() {
  // put your main code here, to run repeatedly:
  Serial.println (myFunction(5));
  delay(100);
}


No compiler errors

Using board '328' from platform in folder: C:\Users\Shmuel\AppData\Local\Arduino15\packages\MiniCore\hardware\avr\2.2.1
Using core 'MCUdude_corefiles' from platform in folder: C:\Users\Shmuel\AppData\Local\Arduino15\packages\MiniCore\hardware\avr\2.2.1
Detecting libraries used...
"C:\\Users\\Shmuel\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-g++" -c -g -Os -w -std=gnu++17 -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=8000000L -DARDUINO=10607 -DARDUINO_AVR_ATmega328 -DARDUINO_ARCH_AVR "-IC:\\Users\\Shmuel\\AppData\\Local\\Arduino15\\packages\\MiniCore\\hardware\\avr\\2.2.1\\cores\\MCUdude_corefiles" "-IC:\\Users\\Shmuel\\AppData\\Local\\Arduino15\\packages\\MiniCore\\hardware\\avr\\2.2.1\\variants\\standard" "C:\\Users\\Shmuel\\AppData\\Local\\Temp\\arduino-sketch-B7601F749C2ED9ABBB3B67729B65E0D2\\sketch\\sketch_jan30a.ino.cpp" -o nul
Generating function prototypes...
"C:\\Users\\Shmuel\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-g++" -c -g -Os -w -std=gnu++17 -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=8000000L -DARDUINO=10607 -DARDUINO_AVR_ATmega328 -DARDUINO_ARCH_AVR "-IC:\\Users\\Shmuel\\AppData\\Local\\Arduino15\\packages\\MiniCore\\hardware\\avr\\2.2.1\\cores\\MCUdude_corefiles" "-IC:\\Users\\Shmuel\\AppData\\Local\\Arduino15\\packages\\MiniCore\\hardware\\avr\\2.2.1\\variants\\standard" "C:\\Users\\Shmuel\\AppData\\Local\\Temp\\arduino-sketch-B7601F749C2ED9ABBB3B67729B65E0D2\\sketch\\sketch_jan30a.ino.cpp" -o "C:\\Users\\Shmuel\\AppData\\Local\\Temp\\arduino-sketch-B7601F749C2ED9ABBB3B67729B65E0D2\\preproc\\ctags_target_for_gcc_minus_e.cpp"
"C:\\Users\\Shmuel\\AppData\\Local\\Arduino15\\packages\\builtin\\tools\\ctags\\5.8-arduino11/ctags" -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives "C:\\Users\\Shmuel\\AppData\\Local\\Temp\\arduino-sketch-B7601F749C2ED9ABBB3B67729B65E0D2\\preproc\\ctags_target_for_gcc_minus_e.cpp"
Compiling sketch...
"C:\\Users\\Shmuel\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-g++" -c -g -Os -Wall -Wextra -std=gnu++17 -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -mmcu=atmega328p -DF_CPU=8000000L -DARDUINO=10607 -DARDUINO_AVR_ATmega328 -DARDUINO_ARCH_AVR "-IC:\\Users\\Shmuel\\AppData\\Local\\Arduino15\\packages\\MiniCore\\hardware\\avr\\2.2.1\\cores\\MCUdude_corefiles" "-IC:\\Users\\Shmuel\\AppData\\Local\\Arduino15\\packages\\MiniCore\\hardware\\avr\\2.2.1\\variants\\standard" "C:\\Users\\Shmuel\\AppData\\Local\\Temp\\arduino-sketch-B7601F749C2ED9ABBB3B67729B65E0D2\\sketch\\sketch_jan30a.ino.cpp" -o "C:\\Users\\Shmuel\\AppData\\Local\\Temp\\arduino-sketch-B7601F749C2ED9ABBB3B67729B65E0D2\\sketch\\sketch_jan30a.ino.cpp.o"
Compiling libraries...
Compiling core...
Using precompiled core: C:\Users\Shmuel\AppData\Local\Temp\arduino-core-cache\core_9c196377d185d9ffa9cbddf6838099bc.a
Linking everything together...
"C:\\Users\\Shmuel\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-gcc" -Wall -Wextra -Os -Wl,--gc-sections -mmcu=atmega328p -o "C:\\Users\\Shmuel\\AppData\\Local\\Temp\\arduino-sketch-B7601F749C2ED9ABBB3B67729B65E0D2/sketch_jan30a.ino.elf" "C:\\Users\\Shmuel\\AppData\\Local\\Temp\\arduino-sketch-B7601F749C2ED9ABBB3B67729B65E0D2\\sketch\\sketch_jan30a.ino.cpp.o" "C:\\Users\\Shmuel\\AppData\\Local\\Temp\\arduino-sketch-B7601F749C2ED9ABBB3B67729B65E0D2/..\\arduino-core-cache\\core_9c196377d185d9ffa9cbddf6838099bc.a" "-LC:\\Users\\Shmuel\\AppData\\Local\\Temp\\arduino-sketch-B7601F749C2ED9ABBB3B67729B65E0D2" -lm
"C:\\Users\\Shmuel\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-objcopy" -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 "C:\\Users\\Shmuel\\AppData\\Local\\Temp\\arduino-sketch-B7601F749C2ED9ABBB3B67729B65E0D2/sketch_jan30a.ino.elf" "C:\\Users\\Shmuel\\AppData\\Local\\Temp\\arduino-sketch-B7601F749C2ED9ABBB3B67729B65E0D2/sketch_jan30a.ino.eep"
"C:\\Users\\Shmuel\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-objcopy" -O ihex -R .eeprom "C:\\Users\\Shmuel\\AppData\\Local\\Temp\\arduino-sketch-B7601F749C2ED9ABBB3B67729B65E0D2/sketch_jan30a.ino.elf" "C:\\Users\\Shmuel\\AppData\\Local\\Temp\\arduino-sketch-B7601F749C2ED9ABBB3B67729B65E0D2/sketch_jan30a.ino.hex"
cmd /C echo. && "C:\\Users\\Shmuel\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-objdump" --disassemble --source --line-numbers --demangle --section=.text "C:\\Users\\Shmuel\\AppData\\Local\\Temp\\arduino-sketch-B7601F749C2ED9ABBB3B67729B65E0D2/sketch_jan30a.ino.elf" > "C:\\Users\\Shmuel\\AppData\\Local\\Temp\\arduino-sketch-B7601F749C2ED9ABBB3B67729B65E0D2/sketch_jan30a.ino_atmega328p_8000000L.lst"
 

"C:\\Users\\Shmuel\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-size" -A "C:\\Users\\Shmuel\\AppData\\Local\\Temp\\arduino-sketch-B7601F749C2ED9ABBB3B67729B65E0D2/sketch_jan30a.ino.elf"
Sketch uses 2166 bytes (6%) of program storage space. Maximum is 32256 bytes.
Global variables use 188 bytes (9%) of dynamic memory, leaving 1860 bytes for local variables. Maximum is 2048 bytes.

You are missing thinking about what you are using the variable for. If you are going to set the variable to some known value before you use it then you don't need to initialise it. What would be the point if as soon as you use it you change it to something useful?

In this case if aa is not initialized, can it RETURN random data?

In the example in reply #14 you must initialise aa to guarantee it returns a known value reliably.

However in some of your earlier examples there is no need to initialise because they have a known value set before they see used.

Which means:

byte myFunction(byte param = 0) {
  byte aa = 0;
  if (digitalRead(param) == HIGH) {
    aa = 1;
  }
  return aa;
}

void setup() {
  Serial.begin(115200);
}

void loop() {
  Serial.println(myFunction());
  delay(100);
}

"aa" will default to "0"

vs

byte myFunction(byte param = 0) {
  byte aa;
  if (digitalRead(param) == HIGH) {
    aa = 1;
  }
  return aa;
}

void setup() {
  Serial.begin(115200);
}

void loop() {
  Serial.println(myFunction());
  delay(100);
}

aa may return random data.
Correct?

Just want to make sure that I understand.
Please see the last example.

Even more reason to always initialise... the compiler doesn't always get it right!

Consider this even more confusing example...

int myFunction(byte param) 
{
  int aa;

  if (digitalRead(param) == LOW)
    aa = 3;
  else
    Serial.println(aa);

  Serial.println(aa);
  return aa;
}

void setup()
{
  Serial.begin(115200);
  pinMode(5, INPUT_PULLUP);
}

void loop()
{
  Serial.println (myFunction(5));
  delay(10000);
}

2 consecutive print statement that give different results ! The compiler is confused...

10:53:25.679 -> 0
10:53:25.679 -> 3
10:53:25.679 -> 3