Let's consider this:
case 0:
my_array[] = {DATA HERE};
exec_func(myarray);
This is not quite valid C++, but let's pretend you get the syntax right
to make it work. The problem is: doing this will not help you save
memory. Where do you think the compiler is going to store {DATA HERE}
?
In memory, right. It will be stored as an anonymous array. Then the
initialization of my_array
will make a second copy of the data in
memory, this time in a named array.
You can avoid this second copy by naming your arrays of constants, and
passing the correct one to your function:
// At global scope:
const int my_array_0[] = {...};
const int my_array_1[] = {...};
// Within the switch/case:
case 0:
exec_func(my_array_0);
You can even avoid the switch
/case
altogether by using an array of
pointers, but that is irrelevant to your current problem.
Your idea of initializing only the array you actually need can work if
you manage to do it procedurally, i.e. implementing some recipe with
instructions, rather than copying a set of constant:
case 0: {
int my_array[array_size];
for (int i = 0; i < array_size; i++) {
my_array[i] = some_expression_to_compute_this_array_item;
}
exec_func(myarray);
}
This is not always feasible though.
If you really have to store the constants in the program, and you are
using an AVR-based Arduino (like the Uno, Mega, Micro...), then you can
save RAM by storing the arrays of constants in flash memory, and copying
only the one you need to RAM:
// At global scope:
const int my_array_0[] PROGMEM = {...};
const int array_size_0 = sizeof my_array_0 / sizeof my_array_0[0];
const int my_array_1[] PROGMEM = {...};
const int array_size_1 = sizeof my_array_1 / sizeof my_array_1[0];
// Within the switch/case:
case 0: {
int my_array[array_size_0]; // array in RAM
memcpy_P(my_array, my_array_0, sizeof my_array);
exec_func(my_array);
}
case 1: {
int my_array[array_size_1]; // array in RAM
memcpy_P(my_array, my_array_1, sizeof my_array);
exec_func(my_array);
}
Check the documentations of PROGMEM and memcpy_P()
for
the details.
If you go this route, you may consider modifying the function
exec_func()
so that it expects its parameter to be a pointer to flash
instead of a pointer to RAM. Then you will completely avoid the copy in
RAM.
Edit: expanding on the idea of passing a pointer to flash.
The C++ compiler doesn't really know the difference between a pointer to
RAM and a pointer to flash. If you want to pass a pointer to flash to a
function, you have to write the function in such a way that it expects a
pointer to flash. For example, this function prints out the contents of
a flash-based array:
// The argument should be a pointer to flash.
void exec_func(const int *data)
{
for (int i = 0; i < array_size; i++) {
int number = pgm_read_word(&data[i]);
Serial.println(number);
}
}
Note that the array is not accessed directly (evaluating data[i]
would
give garbage). Instead, the address of the element you want (&data[i]
,
a flash address) is passed to the macro pgm_read_word()
, which uses
inline assembly to get the relevant data from the flash.
Now you can call this function passing it the address of a PROGMEM
array, as in exec_func(my_array_0);
.
Just for completeness, I will show you how to use an array of pointers
to avoid the switch
/case
construct:
const int my_array_0[] PROGMEM = {...};
const int my_array_1[] PROGMEM = {...};
...
const int *arrays[] = {my_array_0, my_array_1, ...};
int looper = 0;
void loop()
{
exec_func(arrays[looper]);
if (++looper == number_of_arrays) looper = 0;
}
Note that here arrays
is a RAM-based array. That's why you can access
the elements directly as arrays[looper]
. These elements, however, are
pointers to flash-based arrays. If you have so many arrays that arrays
gets too big, you might consider putting it also in flash.
my_array[]
defined in case 1 would be automatically destroyed at the end of case 1. Incidentally, if you define variables within a case, the case block should be enclosed in brackets { } or you get compiler warnings.exec_func(myarray)
? What is the data type ofmy_array[]
? Does the function take in amy_array[]
or does it take in a pointer to the array? Whether themy_array[]
only be used within thecase 0
or does it uses somewhere else? Meanwhile I'd suggest you read Learn C++. BTW, thenew/delete
is used for dynamic allocated memory using command likemalloc()
, it does not applicable to static array creation.