Array from function only partial

Hello guys (n’girls)

I have a strange behavior when dealing with Arrays and return them from a function. Simple words: Why does my code only print the first 2 elements for the array?

int today;

void setup() {
  Serial.begin(9600);
  today = 1;
  
  byte* numArray = getNumber(today); 
  Serial.print("Displaying number ");
  Serial.print(today);
  Serial.print(" (");
  Serial.print(sizeof(numArray));
  Serial.print(") :");

  for (int i = 0; i < sizeof(numArray); i++) {
    int led = numArray[i];
    Serial.print(led); 
    Serial.print(" ");
  }
}

void loop() {
true;
}

byte *getNumber(int x) {  
  switch (x) {
    case 1: static byte one[8] = {6,9,10,20,23,34,37,49}; return(one); break;
  }
}

Monitor output:

Displaying number 1 (2) :6 9

and return them from a function

You can’t return an array from a function.

Your function isn’t returning an array. It is returning a pointer to some data.

Think about that pointer. How big is it? That was the question you asked the sizeof() macro. It told you, correctly, that the pointer is 2 bytes. You assumed that it was telling you how much memory the pointer points to. The answer to that is “the rest”, which, of course, is not useful information.

You need the function to tell you how much memory the pointer points to.

byte *getNumber(int x) {  
  switch (x) {
    case 1: static byte one[8] = {6,9,10,20,23,34,37,49}; return(one); break;
  }
}

You also shouldn't try to return a pointer to local data from a function. As soon as the function exits, that local variable "one" goes out of scope. So you no longer own that memory. Some of the data may still be there if the processor hasn't written over it yet, but there are no guarantees and the entire thing may be corrupted.

If you want to do what you're trying to do, then the caller needs to allocate the array and pass a pointer to it to the function.

You also shouldn’t try to return a pointer to local data from a function. As soon as the function exits, that local variable “one” goes out of scope. So you no longer own that memory

Except that the array is static, so it remains in memory even when the function ends.

Delta_G:
If you want to do what you're trying to do, then the caller needs to allocate the array and pass a pointer to it to the function.

Thanks for your reply. Is this applicable to my code? I am getting desperate with this programming language :frowning:

You can’t ask for the number of elements in an array in C/C++. You have to tell the program how big the array is!

Mark

You can’t ask for the number of elements in an array in C/C++. You have to tell the program how big the array is!

Not always true. It depends on the scope of the array. You can use the macro:

#define ARRAYSIZE(x)   (sizeof(x) / sizeof(x[0]))

// example:

   for (i = 0; i < ARRAYSIZE(myArray); i++) {
      // whatever...
   }

which does determine the number of elements in the array, but only if the array is in scope.

Make life simple and create the array as a global variable?

...R

Ok guys, I simplified the entire code now to show what’s the real goal of my sketch. I have 50 WS2801 LEDs which I want to align to a 4x7 matrix and display number 0 to 31 (later maybe more) with the help of the FastLED library. The matrix looks like this

As you can see, to display a “1”, I need to illuminate LED 6,9,10,20,23,34,37 and 49. That’s why I create an array called one

byte one[8] = {6,9,10,20,23,34,37,49};

So I do this for all digits from 0 to 31.
Next I read the current day from the RTC which gives me that as an integer 1…31. So what I finally want is to pick the right array depending on the current day as number. Something like this:

byte one[8] = {6,9,10,20,23,34,37,49}; 
byte two[x] = {n,n,n,n,n,n,n,n,n,n}; // next number, etc

int today = 1; // read from RTC
  
 switch (today)
    case 1: //define a new array called numArray and point to "one[]" with the same size
    case 2: // define the array numArray here and poin to "two[]"
  }
 
  for (int i = 0; i < sizeof(numArray); i++) {
    int led = numArray[i];
   // illuminate that led number
  }
}

I get stuck here and I am pretty sure there must be a way to program this. I appreciate any help. If this approach is not possible, do you know any methods on how to handle my LED matrix? I also tried by creating a 2d array and parsing every single LED to be on (1) or off (0)

/*                                       1                   2                   3                   4                   5
LED Matrix of WS2801   1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0  */
int matrix[31][50] = {{0,0,0,0,1,1,0,1,0,0,1,0,0,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0},
                      {0,0,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0},
                      ....
                      ....

but that does not work beause the array is too big for the SRAM.

Something like this

A 2D array makes more sense, and will make it much easier to access the correct row.

int matrix[31][50] = {{0,0,0,0,1

Using 16 bits to hold one bit is a bit of a waste, don't you think. No pun intended.

With an int you are using 16 bits to hold 1 bit of data. Doh!

Mark

yeah you're right. But even if I change it to byte I got the same problem of SRAM =(
Any other solutions?

The longest integer in the Arduino system seems to be a long which consists to 32 bits - pity there isn't a 64 bit version.

But you could use two unsigned longs (imagine them as being end to end) where each of the lower 50 bits represents the status for 1 led. That way all 31 numbers could be represented in 64 longs or 256 bytes. (I'm not sure if this is a saving). Of course all these constant values could be in PROGMEM.

In addition, if you use a suitable union with another pair of longs you could probably arrange for the leds to switched on directly by outputting the relevant bytes. It might mean that the bit for (say) led 23 should be in (say) the 18th place to simplify aligning bits for the connection to the hardware.

...R

Robin2:
The longest integer in the Arduino system seems to be a long which consists to 32 bits - pity there isn't a 64 bit version.

The long long type is 64 bits wide.

PeterH:

Robin2:
The longest integer in the Arduino system seems to be a long which consists to 32 bits - pity there isn't a 64 bit version.

The long long type is 64 bits wide.

That would suit the suggestion I made in the earlier post. It doesn't seem to be mentioned in the Reference section.

...R

Your matrix is easily done using my BitBool library: http://forum.arduino.cc/index.php?topic=128407.0

The matrix uses 217 bytes of RAM. Give it a try and watch the serial monitor.

#include <BitBool.h>

BitBool< 50, true > matrix[ 31 ] = {  //The true makes the LSB bit 8 rather than bit 0
  { B11001100, B00000001, B11110000, B10101010, B11001100, B00000001, B11000000 }, //Last 6 bits aren't used.
  { B11001100, B00000001, B11110000, B10101010, B11001100, B00000001, B11000000 },
  { B11001100, B00000001, B11110000, B10101010, B11001100, B00000001, B11000000 },
  { B11001100, B00000001, B11110000, B10101010, B11001100, B00000001, B11000000 },
  { B11001100, B00000001, B11110000, B10101010, B11001100, B00000001, B11000000 },
  { B11001100, B00000001, B11110000, B10101010, B11001100, B00000001, B11000000 },
  //...
};

void setup() {
  
  Serial.begin( 9600 );
  Serial.print( "\r\nMatrix array:\r\n" );
  
  for( char cnt = 0 ; cnt < 31 ; ++cnt ){
    for( char cnt1 = 0 ; cnt1 < 50 ; ++cnt1 ){
      
      Serial.print( matrix[ cnt ][ cnt1 ] );
    }
    Serial.print( ",\r\n" );
  }
  
}

void loop() {}

pYro_65: slick!

econjack:
pYro_65: slick!

Cheers, my BitBool has many neat uses in the micro controller world.

@op
If you are happy with using a flat array ( single dimension ), then the matrix only uses 194 bytes, wasting only 2 bits.

BitBool< ( 31 * 50 ), true > matrix = { 
   B11001100, B00000001, B11110000, B10101010, B11001100, B00000001, B11000000 ,
   B11001100, B00000001, B11110000, B10101010, B11001100, B00000001, B11000000 ,
   B11001100, B00000001, B11110000, B10101010, B11001100, B00000001, B11000000 ,
   B11001100, B00000001, B11110000, B10101010, B11001100, B00000001, B11000000 ,
   B11001100, B00000001, B11110000, B10101010, B11001100, B00000001, B11000000 ,
   B11001100, B00000001, B11110000, B10101010, B11001100, B00000001, B11000000 ,
};

BitBool looks like a slick tool, but I don't immediately see its relevance here.

The "matrix" that the OP needs is just static data to record the bit positions associated with different digits. It may be tedious to work them all out but it only needs to be done once and after that it won't need to change.

Can you use BitBool to produce a "byte" from some of the bits in a row of the matrix - something like this
byte x = matrix[12][16]:

Which would be the similar to creating a union with a long long and an array of 8 bytes, but might be more flexible.

...R

Robin2:
It doesn't seem to be mentioned in the Reference section.

The Arduino reference coverage of C++ language features is pretty patchy.