Initializing and storing arrays and passing them as parameters

I'd like to settle this once and for ever, because I've been fumbling around this and failing, and then went for some workarounds.

My programming background is Java, C#, Python and handful of older programming languages (ASM, for god's sake), but relatively little of C++. The Arduino where I code now, is Mega.

So, I am basically looking for the following:

  1. Passing array as function parameter
    Here's the function
void processArray(int a[], int size)
{
  for (int i=0; i<size; i++)
  {
    // Do processing with a[i]
  }
}

This works fine:

void setup()
{
  int a[4] = {0, 1, 2, 3};
  processArray(a, 4);
}

But why can't I do the following?

void setup()
{
  processArray({0, 1, 2, 3}, 4);
}

Am I stuck to waste a variable and line of code always I want to pass an array to a function?

  1. If I want to store an array in class variable, how do I do it? I am interested in both fixed size and variable size array case. How to declare the class variable in the header file and how to code the method that takes the array parameter and stores the data in the class variable?

  2. If I want to establish dynamic array (ie, variable size, if there's enough space in memory), how do I do it?

  3. If I want to establish variable size array of objects, how do I do it? With "object" I here understand instances of my custom class.

Passiday:
Am I stuck to waste a variable and line of code always I want to pass an array to a function?

I would suggest declaring the array as const and then passing it into the function. The compiler should take care of making sure you're not wasting any space.

  1. If I want to store an array in class variable, how do I do it? I am interested in both fixed size and variable size array case. How to declare the class variable in the header file and how to code the method that takes the array parameter and stores the data in the class variable?

I'm not sure what problem you're running into here. Can you provide a code example that isn't working for you?

  1. If I want to establish dynamic array (ie, variable size, if there's enough space in memory), how do I do it?

Arduino dynamic memory management is not so great. Maybe take a look at this thread.

http://forum.arduino.cc//index.php?topic=44393.15

Specifically:

I fully agree with this, but would add to it. NEVER use malloc or any of its derivatives in your projects.

There is only a single pool of RAM memory and there is just not enough of it to make this a viable approach on 8-bit AVR's such as the AtMega328. Although more than useful on other platforms (such as Windows, Mac, Unix) it is asking for trouble on Arduino's. When frequently allocating/freeing memory with global references, you run the risk of fragmented memory and soon "disaster" strikes when stack and/or other memory is overwritten. It is very difficult at best to predict and guard against such errors when writing software and even worse to debug when issues materialize. This is also a major source of errors on platforms where memory is available in abundance (memory leaks accumulating over time).

It may be educational to explore the finer arts of dynamic C++ classes, but Arduino is not the right platform for this. I would also stay clear of any Arduino library that make use of dynamic memory.

joshuabardwell:
I would suggest declaring the array as const and then passing it into the function. The compiler should take care of making sure you're not wasting any space.

The question is whether that's the only way to do it - through a variable. You say "suggest", as if there is a direct way to call a function with array literal in parameter. I mean, sometimes the code just looks nicer that way.

  1. If I want to store an array in class variable, how do I do it? I am interested in both fixed size and variable size array case. How to declare the class variable in the header file and how to code the method that takes the array parameter and stores the data in the class variable?

I'm not sure what problem you're running into here. Can you provide a code example that isn't working for you?

Here is: (header, class code, call from the main)

// Header
class TestClass
{
  public:
    TestClass(int intArr[]);
  private:
    String _intArr;
};
// Class code
TestClass::TestClass(int intArr[])
{
  _intArr = intArr;
}
// Object init call
int a[4] = {0, 1, 2, 3};
TestClass tc1(a);
int b[5] = {4, 5, 6, 7, 8};
TestClass tc2(b);

I reckon there could be several ways how to do it properly, ie, passing the array by reference and storing just this reference, etc. Well, I need one way that actually works :stuck_out_tongue:

  1. If I want to establish dynamic array (ie, variable size, if there's enough space in memory), how do I do it?

Arduino dynamic memory management is not so great. Maybe take a look at this thread.

So, you basically suggest sticking with fixed size arrays, estimating reasonable max size and taking up all the memory at init? Well, that's a way how to deal with it, unless there would be several such arrays, growing and shrinking at run time.

Passiday:
The question is whether that's the only way to do it - through a variable. You say "suggest", as if there is a direct way to call a function with array literal in parameter. I mean, sometimes the code just looks nicer that way.

The problem with array literals, as I understand it, is that the compiler doesn't know what type they are. You would expect that, since they are numerical literal values, they would default to int, but that doesn't seem to work. Some possible workarounds include:

// function template
void foo(int[] arrayParam);

// This approach declares a variable within the scope of the function call and then passes it into the function
foo(int[4] i = {1, 2, 3, 4}); 

// This approach typecasts the array
foo((int[4]){1, 2, 3, 4});

These are just two suggestions--I don't know if they'll work, but you can give them a try.

I reckon there could be several ways how to do it properly, ie, passing the array by reference and storing just this reference, etc. Well, I need one way that actually works :stuck_out_tongue:

If I understand correctly, this is basically the same question as number 1, just applied in a class method (constructor) vs. a non-class method. The answer should be the same.

So, you basically suggest sticking with fixed size arrays, estimating reasonable max size and taking up all the memory at init? Well, that's a way how to deal with it, unless there would be several such arrays, growing and shrinking at run time.

The consensus on the topic seems to be that you should try as hard as you can to avoid dynamic memory management on small-memory, embedded systems like the Arduino. If you absolutely require dynamic memory management, you can use malloc(), but there are all kinds of quirks that you need to be aware of. My hunch would be that if you are working with large arrays that are growing and shrinking, you are probably going to run out of SRAM anyway, although being on a Mega, you have a little more breathing room.

... also, if you do a little google searching, you can find libraries for Arduino that implement dynamic linked lists such as queues and stacks. In that, case, at least the kinks should have been worked out for you. I'd suggest going that way vs. trying to roll your own.

joshuabardwell:
The problem with array literals, as I understand it, is that the compiler doesn't know what type they are. You would expect that, since they are numerical literal values, they would default to int, but that doesn't seem to work. Some possible workarounds include:

foo(int[4] i = {1, 2, 3, 4}); 

foo((int[4]){1, 2, 3, 4});

Unfortunately neither of the alternatives you suggest compile.

I reckon there could be several ways how to do it properly, ie, passing the array by reference and storing just this reference, etc. Well, I need one way that actually works :stuck_out_tongue:

If I understand correctly, this is basically the same question as number 1, just applied in a class method (constructor) vs. a non-class method. The answer should be the same.

Well, not quite, because the array passed as parameter has to be copied to the field variable. I get the compiler complaining "incompatible types in assignment of ‘int*’ to ‘int [0]’". Perhaps I have to declare the _intArr in the header somehow differently. Currently there is int _intArr[], and simple assignment (parameter variable to class field variable) _intArr = intArr; just doesn't compile.

The consensus on the topic seems to be that you should try as hard as you can to avoid dynamic memory management on small-memory, embedded systems like the Arduino. If you absolutely require dynamic memory management, you can use malloc(), but there are all kinds of quirks that you need to be aware of. My hunch would be that if you are working with large arrays that are growing and shrinking, you are probably going to run out of SRAM anyway, although being on a Mega, you have a little more breathing room.

Ok, thanks, I'll look up those libraries you refer to. But I have to settle simpler matters like the ones we discuss above.

Passiday:
Unfortunately neither of the alternatives you suggest compile.

Sorry. The second one is a construct known as a compound literal, but I guess the Arduino compiler doesn't support it. I think it may be a C99 feature, which would explain it. Using that keyword, I found a Stack Overflow topic that seems to exactly address your question, and it seems like the answer is, "You can't do that."

For an understanding of why you can't create an array "on the fly" like you are trying to do, you should read up on the close relationship between arrays and pointers. You are NOT passing an array to a function that expects an array. You are passing the address of the first element in the array. That's why you need to pass, separately, the size of the array. Given only the starting address, the function has no way of determining the length of the array. If the array is well defined (think NULL terminated arrays of chars), then the called function can look for the "stop" sign in the array, and know to stop. Usually, though, there is no way to include any kind of marker in the array to indicate that this is the end of the valid data in the array. An array of floats that needs to be able to include positive and negative values can't define -1.0 to mean stop!

The C++ compiler used to compile code for the Arduino does not know how to define an array "on the fly", and pass the address to a function. Not the least of the issues is not knowing the type of the array to create (float, char, int, byte, double, uint8_t, boolean, etc.).

The closest you can get to defining an array value 'on the fly' is to define and initialise a local variable - and in this case the size can be dynamic in the sense that the size becomes fixed at the point the variable is instantiated, not at compile time. However, it does still require you to define and then use a variable - you can't (as far as I know) define an array literal value in this version of C++ except in a variable initialisation expression.