Problem: initializing member array before loop

Hello dear community,

I´ve been experiencing a scope problem that I don´t know how to solve.
I am trying to initialize an object member before the loop(). I tried different ways, but all of them return 0 even though I´m convinced, that the actual inititlization is okay. I'm not getting any compile errors, I simply get a zero, where I think I already assigned a value.

  1. Attempt: initializing in the constructor of the object.
//----Obj.h
#define SIZE 5

class Obj
{
  public:
  Obj();
  void getval(uint8_t pos);

  private:
  std::array <uint8_t, SIZE> member;

//----Obj.cpp
Obj::Obj()
{
  std::array <uint8_t, SIZE> member = {0, 1, 2, 3, 4 };
}

void getval(uint8_t pos) {
  Serial.println("Loop: "+String(member[pos]));
}

//----main.ino
Obj MyObj();

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

loop() {
  MyObj.getval (0);
}

Result:
Loop: 0
Loop: 0
Loop: 0
...

  1. Attempt: initializing in function in setup.
//----Obj.h
#define SIZE 5

class Obj
{
  public:
  Obj();
  void begin();
  void getval(uint8_t pos);

  private:
  std::array <uint8_t, SIZE> member;

//----Obj.cpp
Obj::Obj() {}

void begin() {
  std::array <uint8_t, SIZE> member = {0, 1, 2, 3, 4 };
  Serial.println("Setup: "+String(member[1]));
}

void getval(uint8_t pos) {
Serial.println("Loop: "+String(member[pos]));
}

//----main.ino
Obj MyObj();

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

loop() {
  MyObj.getval (1);
}

Result:
Setup: 1
Loop: 0
Loop: 0
...

I really want to avoid putting the begin function in the main loop (didn't even try it yet), since the array needs to be non-static and non-const later on in the project.
From my understanding the obejct is global, hence the members should be too (except of being private), so this should work.
Where am I wrong?

Thanks in advance
Cheers
Jokinger

the posted code had numerous errors

here's a re-write the generated the following

output

Loop: 1
Loop: 2
Loop: 3
Loop: 99
Loop: 2001
#define SIZE 5

class Obj {
    int member [SIZE] = { 1, 2, 3, 99, 2001 };

  public:
    Obj ()                    { }

    void getval (uint8_t pos) {
        Serial.print    ("Loop: ");
        Serial.println  (member[pos]);
    }
} myObj;

// -----------------------------------------------------------------------------
void setup (){
    Serial.begin (9600);

    for (int n = 0; n < SIZE; n++)
        myObj.getval (n);
}

void loop () {
}
2 Likes

I am no expert on C++ but it looks like a local variable that simply shadows your real “member“.

errors from posted code

Tst:11:8: error: 'array' in namespace 'std' does not name a template type
   std::array <uint8_t, SIZE> member;
        ^~~~~
C:\stuff\SW\Arduino\_Others\Tst\Tst.ino:14:1: warning: extra qualification 'Obj::' on member 'Obj' [-fpermissive]
 Obj::Obj()
 ^~~
Tst:14:1: error: 'Obj::Obj()' cannot be overloaded
Tst:7:3: error: with 'Obj::Obj()'
   Obj();
   ^~~
Tst:19:6: error: 'void Obj::getval(uint8_t)' cannot be overloaded
 void getval(uint8_t pos) {
      ^~~~~~
Tst:8:8: error: with 'void Obj::getval(uint8_t)'
   void getval(uint8_t pos);
        ^~~~~~
C:\stuff\SW\Arduino\_Others\Tst\Tst.ino:26:7: warning: ISO C++ forbids declaration of 'setup' with no type [-fpermissive]
 setup(){
       ^
C:\stuff\SW\Arduino\_Others\Tst\Tst.ino:30:6: warning: ISO C++ forbids declaration of 'loop' with no type [-fpermissive]
 loop() {
      ^
Tst:32:1: error: expected '}' at end of input
 }
 ^
C:\stuff\SW\Arduino\_Others\Tst\Tst.ino: In constructor 'Obj::Obj()':
Tst:16:8: error: 'array' is not a member of 'std'
   std::array <uint8_t, SIZE> member = {0, 1, 2, 3, 4 };
        ^~~~~
Tst:16:22: error: expected primary-expression before ',' token
   std::array <uint8_t, SIZE> member = {0, 1, 2, 3, 4 };
                      ^
Tst:16:30: error: 'member' was not declared in this scope
   std::array <uint8_t, SIZE> member = {0, 1, 2, 3, 4 };
                              ^~~~~~
C:\stuff\SW\Arduino\_Others\Tst\Tst.ino:16:30: note: suggested alternative: 'memmem'
   std::array <uint8_t, SIZE> member = {0, 1, 2, 3, 4 };
                              ^~~~~~
                              memmem
C:\stuff\SW\Arduino\_Others\Tst\Tst.ino: In member function 'void Obj::getval(uint8_t)':
Tst:20:34: error: 'member' was not declared in this scope
   Serial.println("Loop: "+String(member[pos]));
                                  ^~~~~~
C:\stuff\SW\Arduino\_Others\Tst\Tst.ino:20:34: note: suggested alternative: 'memmem'
   Serial.println("Loop: "+String(member[pos]));
                                  ^~~~~~
                                  memmem
C:\stuff\SW\Arduino\_Others\Tst\Tst.ino: In member function 'int Obj::setup()':
C:\stuff\SW\Arduino\_Others\Tst\Tst.ino:28:1: warning: no return statement in function returning non-void [-Wreturn-type]
 }
 ^
C:\stuff\SW\Arduino\_Others\Tst\Tst.ino: In member function 'int Obj::loop()':
Tst:31:3: error: invalid use of member function 'Obj Obj::MyObj()' (did you forget the '()' ?)
   MyObj.getval (0);
   ^~~~~
Tst:31:3: error: invalid use of member function 'Obj Obj::MyObj()' (did you forget the '()' ?)
C:\stuff\SW\Arduino\_Others\Tst\Tst.ino:32:1: warning: no return statement in function returning non-void [-Wreturn-type]
 }
 ^
C:\stuff\SW\Arduino\_Others\Tst\Tst.ino: At global scope:
Tst:32:1: error: expected unqualified-id at end of input
exit status 1
'array' in namespace 'std' does not name a template type

1 Like

Yes, Variable Shawdowing.
The local variable being initalized is destroyed when the function (constructor or begin) ends.

1 Like

It still works with std::array

/* Online C++ Compiler and Editor */
#include <iostream>
#include <cstdint>

#include <algorithm>
#include <array>
#include <iterator>
#include <string>

using namespace std;

#define SIZE 5

class Obj
{
  public:

  //private:
  std::array <uint8_t, SIZE> member = {0, 1, 2, 3, 4 };

} ;

Obj myObj ;

int main()
{
    for ( int i = 0; i < SIZE ; i++ )    {
       std::cout << (uint16_t)myObj.member[i] << endl; 
    }   
   return 0;
}
1 Like

Thank you. You´re right about the mistakes. I only posted it as an example.
But you are using the variable public, which I don´t attend to declare it.

Why is it local though?
myObj is initialized before the setup, so it should be global.
Thanks for the link. I´ll browse through it

If you're asking for (free) help, common courtesy would suggest that you post your actual code (or an abbreviated) version so that members don't waste time fixing errors that aren't part of your problem.

Regarding initialization ... most efficient would be an initializer list in the constructor:

#define SIZE 5

class Obj {
  public:
    Obj() : member ( {
      0, 1, 2, 3, 4
    }) {};
    uint8_t getVal(uint8_t pos);

  private:
    std::array <uint8_t, SIZE> member;
};

uint8_t Obj::getVal(uint8_t pos) {
  return member[pos];
}

Obj myObj;

void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial.println();
  for (size_t i = 0; i < SIZE; i++) {
    Serial.println(myObj.getVal(i));
  }
}

void loop() {
}

You've defined it inside the function. That makes it local.

1 Like

There's a bit more to it, so I didn't want to bother you with that stuff, but yes, thank you. I´ll keep it in mind for the next time.

Because it is declared as a local variable. Instead of assigning you are declaring AND assigning.

Compare two pieces of code:

int Global_variable = 10;

void some_function() {

  int Global_Variable = 666;
  Serial.printf("some_function() : Global_Variable is %d\r\n", Global_Variable);
}

void loop() {
  Serial.printf("loop() : Global_Variable is %d\r\n", Global_Variable);
  some_function();
  Serial.printf("loop() : Global_Variable is %d\r\n", Global_Variable);

  delay(1000);
}

And

int Global_variable = 10;

void some_function() {

  Global_Variable = 666;
  Serial.printf("some_function() : Global_Variable is %d\r\n", Global_Variable);
}

void loop() {
  Serial.printf("loop() : Global_Variable is %d\r\n", Global_Variable);
  some_function();
  Serial.printf("loop() : Global_Variable is %d\r\n", Global_Variable);

  delay(1000);
}

Note that in second code fragment, the Global_Variable is assigned in a right way. In first code example the same variable is declared local in the function.

1 Like

Yeah, I saw it when you wrote it.
Thank you.
Fun fact: I was taught wrong but never had problems with it, because I rarely used different intial values than zero.

Thank you very much for elaborating. You´re absolutely right.