Why code don't compile if variable is local? //saving lu to external eeprom using sketchy code

Hi, i want to save unsigned long values to external eeprom. I found code online and i don't understand why i one variable must be global:

unsigned long EEPROM_readLU(int address){
  unsigned long EEPROM_result;

  byte val = readEEPROM(address+3);
  EEPROM_result = (EEPROM_result << 8) | val;
  val = readEEPROM(address+2);
  EEPROM_result= (EEPROM_result << 8) | val;
  val = readEEPROM(address+1);
  EEPROM_result= (EEPROM_result << 8) | val;
  val = readEEPROM(address+0);
  EEPROM_result= (EEPROM_result << 8) | val;

  return EEPROM_result;
}

This code won't compile and i got error "'EEPROM_result' is used uninitialized in this function [-Werror=uninitialized]"

But when i make EEPROM_result a global variable (i define it outside this function) everything works. Why?


This code also won't work if i try to shorten some things like:

 byte val = readEEPROM(address+3);
  EEPROM_result = (EEPROM_result << 8) | val;
--- shorten to --->
 EEPROM_result = (EEPROM_result << 8) | readEEPROM(address+3);

That's weird for me, cuz I always copy somebodys code and try to shorten it a little and i never had such problems yet. Is this code sketchy and i shouldn't use it or i'm just doing something dumb?

Can u give me example how can i do it correctly?
Thanks in advance!


I'm using ESP32 and this is full code:

#include "addresses.h"

void setup() {
  Serial.begin(115200);
  delay(5);
  Wire.begin();
  
  updateEEPROM(0, 5);
  Serial.println(readEEPROM(0));
  updateEEPROM(0, 5);
  Serial.println(readEEPROM(0));
  updateEEPROM(0, 0); 
  Serial.println(readEEPROM(0));

  EEPROM_updateLU(4, 4294967295);
  Serial.println(EEPROM_readLU(4));

  EEPROM_updateLU(4, 0);
  Serial.println(EEPROM_readLU(4));
}

void loop() {

}
  // addresses.h

#define RTC_ADDRESS 0x68
#define PCF8574_1 0x23
#define i2c_address 0x50
#include <Wire.h>

byte readEEPROM(int address) {
  byte rcvData = 0xFF;   // Define byte for received data
 
  Wire.beginTransmission(i2c_address);
 
  // Send memory address as two 8-bit bytes
  Wire.write((int)(address >> 8));   // MSB
  Wire.write((int)(address & 0xFF)); // LSB
 
  // End the transmission
  Wire.endTransmission();
  Wire.requestFrom(i2c_address, 1);   // Request one byte of data at current memory address
 
  rcvData =  Wire.read();
  return rcvData;
}
 
void updateEEPROM(int address, byte val) {
  if (readEEPROM(address) != val){
    Serial.println("OVERWRITING BYTE");
    
    Wire.beginTransmission(i2c_address);
   
    Wire.write((int)(address >> 8));   // MSB
    Wire.write((int)(address & 0xFF)); // LSB
    
    Wire.write(val);
   
    Wire.endTransmission();
    delay(3); 
 }
}
unsigned long EEPROM_readLU(int address){
  unsigned long EEPROM_result;

  byte val = readEEPROM(address+3);
  EEPROM_result = (EEPROM_result << 8) | val;
  val = readEEPROM(address+2);
  EEPROM_result= (EEPROM_result << 8) | val;
  val = readEEPROM(address+1);
  EEPROM_result= (EEPROM_result << 8) | val;
  val = readEEPROM(address+0);
  EEPROM_result= (EEPROM_result << 8) | val;

  return EEPROM_result;
}

void EEPROM_updateLU(int address, unsigned long value){
updateEEPROM(address, value & 0xFF);
updateEEPROM(address+1, (value & 0xFF00) >> 8);
updateEEPROM(address+2, (value & 0xFF0000) >> 16);
updateEEPROM(address+3, (value & 0xFF000000) >> 24);
}
unsigned long EEPROM_result;

byte val = readEEPROM(address+3);
EEPROM_result = (EEPROM_result << 8) | val;

EEPROM_result has garbage in it since you have not initialized it.

It IS being used uninitialized. So initialize it.

  unsigned long EEPROM_result=0;

Local variables are not automatically initialized upon declaration. Global variables are set to zero.

Think about this:

  • if you define it as a global variable - even you do not assign a value to it - it is (will be) initialized!
    global variables are initialized by startup, if not a value assigned - as zero, otherwise with the global assignment of a value
    global variables are always initialized
  • but a local variable is different:
    it sits on the stack, the content of stack is random (something left there).
    If you do not initialize a local variable (on a memory as stack with random content) - compiler will (has to) complain
    Local variables are NEVER initialized (if not done explicetely)

Understand the concept of global variables (and when they are initialized = during startup) and local variables (on stack memory), just allocating memory but no clue about the left random content on this memory.

A local must be initialized - ALWAYS (is NEVER initialized by itself)
a global is INITIALIZED (always) - on STARTUP (as 0 (default) or with assigned value (as .data section copied from ROM to RAM))

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.