Go Down

Topic: Passing arrays to classes (Read 696 times) previous topic - next topic

ardudillo

Aug 05, 2012, 08:51 pm Last Edit: Aug 05, 2012, 08:53 pm by ardudillo Reason: 1
Hello forum, I have what I think is a simple question that is causing me unexpectedly large headaches.

I want to pass an array to a class. In my naive mind, an array is passed by passing (by value) a pointer to its first element. So, the idea goes, the elements of an array declared in a different scope, will be accessible to the methods of the class. The code below explodes:



Quote

class classy {
 
 public:
 
 int a1d[];                      // this should end up pointing to the array myArray in setup()
 
 classy(int passedArray[]) {
   a1d = passedArray;            // this is the line that blows up

 }
 
};



void setup() {
 
 int myArray[5] = { 0, 1, 2, 3, 4 };
 
 classy c = classy(myArray);
 
}

void loop() {}




So, I need to make it so that a method in classy referring to, say, a1d[2] will access myArray[2].

However, I get the following error:

sketch_aug05c.cpp: In constructor 'classy::classy(int*)':
sketch_aug05c:7: error: incompatible types in assignment of 'int*' to 'int [ 0 ]'


So, if I got that right, passedArray[] is considered an integer pointer ('int*', which is what I think a reference to an array is. Note that the constructor is referred to as 'classy::classy(int*)' whereas I have declared it as 'classy(int passedArray[]'), which  I guess amounts to the same thing) but a1d is considered the contents of the first element of an integer array ('int [ 0 ]')? Both are referred to in exactly the same way in the offending line. Am I going crazy or is the compiler linguistically challenged?

majenko

passedArray is a pointer to an array in memory (an "int *").  a1d is an empty array - a similar concept but not quite the same.

Define a1d as "int *a1d;" instead of "int a1d[];" and you can assign it the address of the incoming array.

NOTE

This does NOT copy the contents of the array - it merely points a1d at the same memory as passedArray.  To copy the actual array you will have to manually copy either each entry in the array to a pre-created array of a large enough size, or duplicate the memory, which may lead to memory fragmentation and/or memory leaks.
Get 10% off all 4D Systems TFT screens this month: use discount code MAJENKO10

ardudillo

This is great, thank you.

I certainly don't want the array copied, I just want the object to have the address of the original array so it can access its elements.

One thing I 'd like to add for any poor guys struggling with similar. When stepping this up to 2D arrays, it gets slightly tricky due to operator precedence of * and []. The way to do it is this:

Quote

class classy {
  
  public:
  
  int (*a1d)[5];                      // mind the ()
  
  classy(int passedArray[][5]) {
    a1d = passedArray;
    
    Serial.print("CONSTRUCTOR:\nElement at [1][3] of passed array is ");
    Serial.println(a1d[1][3]);
    Serial.println("Now setting it to -1\n--------------");
    a1d[1][3] = -1;
  }
  
};



void setup() {
  
  
  Serial.begin(57600);
  
  int myArray[][5] = {{ 0, 1, 2, 3, 4 }, { 10, 11, 12, 13, 14 }};
  
  classy c = classy(myArray);
  
  Serial.print("SETUP():\nElement at [1][3] of original array is ");
  Serial.println(myArray
  [1][3]);
  
}

void loop() {}


PaulS

Code: [Select]
    a1d = passedArray;
a1d is now an array of pointers. passedArray is now a 2D array. What is this code supposed to be doing?


ardudillo

It's trying to make "a1d" refer to the same thing in "classy" as "myArray" refers to in setup() so that a1d[m][n] in "classy" will fetch me the same result (by reading the same address) as myArray[m][n] would in setup().

In the grander scheme of things, when this class grows up, it will be used to play tunes on a speaker. The object is pointed towards an array of notes and durations and handles the rest.

So far it's working with no obvious bugs but if you see any problems I 'd be grateful if you 'd point them out.

Go Up