Matt Cashatt
Matt Cashatt

Reputation: 24238

In C++, how do I access values in a multi-dimensional array?

Thanks for looking!

Background

I am building a quadcopter on each arm of which I have placed a strip of RGB addressable LEDs. I am using an Arduino to drive the lights and the Arduino code is C++, a language I don't know very well.

Here is the first StackOverflow question I posted regarding a previous problem I had with this code. It gives you more background about what exactly I am trying to do (if you are interested).

Problem

I have now properly written the array "gpsHoldArr" thanks to the answers to my first question, but I am having trouble accessing it's values.

In the code below, I call toggleLights(gpsHoldArr[x][y]) and pass in a subarray of gpsHoldArr. The subarray should be the result of pointing to a given LED strip ([x]) and then a given step ([y]).

toggleLights should then iterate the array it is passed and send the value of each LED (some number from 1-6) it is on and that LED's red, green, and blue value to the console.

Unfortunately, when I run the code below, I get this error: cannot convert int(*)[3] to int* for argument 1 to 'void toggleLights(int*)'

Any help would be greatly appreciated.

Here's the current code:

//4 arms, 6 steps, 6 leds
int gpsHoldArr[4][6][6][3] = {
  {
    {{255,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
    {{255,0,0}, {255,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
    {{255,0,0}, {255,0,0}, {255,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
    {{255,0,0}, {255,0,0}, {255,0,0}, {255,0,0}, {0,0,0}, {0,0,0}},
    {{255,0,0}, {255,0,0}, {255,0,0}, {255,0,0}, {255,0,0}, {0,0,0}},
    {{255,0,0}, {255,0,0}, {255,0,0}, {255,0,0}, {255,0,0}, {255,0,0}}
},
  {
    {{255,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
    {{255,0,0}, {255,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
    {{255,0,0}, {255,0,0}, {255,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
    {{255,0,0}, {255,0,0}, {255,0,0}, {255,0,0}, {0,0,0}, {0,0,0}},
    {{255,0,0}, {255,0,0}, {255,0,0}, {255,0,0}, {255,0,0}, {0,0,0}},
    {{255,0,0}, {255,0,0}, {255,0,0}, {255,0,0}, {255,0,0}, {255,0,0}}
},
  {
    {{255,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
    {{255,0,0}, {255,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
    {{255,0,0}, {255,0,0}, {255,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
    {{255,0,0}, {255,0,0}, {255,0,0}, {255,0,0}, {0,0,0}, {0,0,0}},
    {{255,0,0}, {255,0,0}, {255,0,0}, {255,0,0}, {255,0,0}, {0,0,0}},
    {{255,0,0}, {255,0,0}, {255,0,0}, {255,0,0}, {255,0,0}, {255,0,0}}
},
  {
    {{255,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
    {{255,0,0}, {255,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
    {{255,0,0}, {255,0,0}, {255,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
    {{255,0,0}, {255,0,0}, {255,0,0}, {255,0,0}, {0,0,0}, {0,0,0}},
    {{255,0,0}, {255,0,0}, {255,0,0}, {255,0,0}, {255,0,0}, {0,0,0}},
    {{255,0,0}, {255,0,0}, {255,0,0}, {255,0,0}, {255,0,0}, {255,0,0}}
}
};

toggleLights(gpsHoldArr[0][0]); //Toggles lights on strip #1, step #1
toggleLights(gpsHoldArr[1][0]); //Toggles lights on strip #2, step #1
toggleLights(gpsHoldArr[2][0]); //Toggles lights on strip #3, step #1
toggleLights(gpsHoldArr[3][0]); //Toggles lights on strip #4, step #1 

void toggleLights(int lights[]){
  for(int i = 0; i <= 6; ++i)
  {
    set_color_led(i, lights[i], lights[i], lights[i]);
  } 
}

void set_color_led(int led, int r, int g, int b){
   Serial.println(led); //Which LED (or "pixel") is it?
   Serial.println(r); //What is the red value?
   Serial.println(g); //What is the green value?
   Serial.println(b); //What is the blue value? 
}

Upvotes: 1

Views: 398

Answers (3)

jstarr
jstarr

Reputation: 480

I don't think that toggleLights() is doing what you think it is doing. Its input is a 1-D array, but you are passing it a 2-D array of size [6][3]. When toggleLights(gpsHoldArr[0][0]); is called, the 1-D memory array that the function sees is {255,0,0,0,0,0}, i.e. the first six values in your array. Then, for each of these values you are calling set_color_led(); and passing the same value for multiple arguments. Unrolling the loop in toggleLights(), this translates to

// set_color_led(i, lights[i], lights[i], lights[i]) for i = {0, ..., 6}
set_color_led(0, 255, 255, 255);
set_color_led(1, 0, 0, 0);
set_color_led(2, 0, 0, 0);
set_color_led(3, 0, 0, 0);
set_color_led(4, 0, 0, 0);
set_color_led(5, 0, 0, 0);
set_color_led(6, 0, 0, 0); // bug here as noted by molbdnilo

This is probably not what you want. I would change the definition of toggleLights() to the following:

void toggleLights(int lights[][3]){
  for(int i = 0; i < 6; ++i)
  {
    set_color_led(i, lights[i][0], lights[i][1], lights[i][2]);
  } 
}

In this case when calling toggleLights(gpsHoldArr[0][0]);, the 2-D array that this function see is

{{255,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}}

and unrolling the loop in toggleLights(), this translates to the following series of function calls:

// set_color_led(i, lights[i][0], lights[i][1], lights[i][2]) for i = {0, ..., 5}
set_color_led(0, 255, 0, 0);
set_color_led(1, 0, 0, 0);
set_color_led(2, 0, 0, 0);
set_color_led(3, 0, 0, 0);
set_color_led(4, 0, 0, 0);
set_color_led(5, 0, 0, 0);

Upvotes: 1

molbdnilo
molbdnilo

Reputation: 66459

I would probably go about it like this, removing some repetition along the way.
(Macro trickery only because of Arduino - on a desktop I would use classes instead of arrays.)

struct LED { int r, g, b; };

#define BLACK  {0, 0, 0}
#define RED    {255, 0, 0}

#define DEFAULT_LEDS \
  { {RED, BLACK, BLACK, BLACK, BLACK, BLACK},\
    {RED, RED,   BLACK, BLACK, BLACK, BLACK},\
    {RED, RED,   RED,   BLACK, BLACK, BLACK},\
    {RED, RED,   RED,   RED,   BLACK, BLACK},\
    {RED, RED,   RED,   RED,   RED,   BLACK},\
    {RED, RED,   RED,   RED,   RED,   RED}}

LED gpsHoldArr[4][6][6] = {
   DEFAULT_LEDS,
   DEFAULT_LEDS,
   DEFAULT_LEDS,
   DEFAULT_LEDS
};


void set_color_led(int index, const LED& led){
   Serial.println(index); //Which LED (or "pixel") is it?
   Serial.println(led.r); //What is the red value?
   Serial.println(led.g); //What is the green value?
   Serial.println(led.b); //What is the blue value? 
}

void toggleLights(LED (&leds)[6]){
  for(int i = 0; i < 6; ++i)  // You had a '<=' bug here.
  {
    set_color_led(i, leds[i]);
  } 
}

toggleLights(gpsHoldArr[0][0]); //Toggles lights on strip #1, step #1

Upvotes: 2

Karthik T
Karthik T

Reputation: 31972

You are passing in a 2D array when your function exists a 1D array (decayed to a pointer).

Can I suggest eliminating array dimmensions by making structs/classes, it will make stuff much clearer.

for e.g

struct Led{
    int r,g,b;
};

void toggleLights(Led lights[]){

Led gpsHoldArr[4][6][6] = 

set_color_led(i, lights[i].r, lights[i].g, lights[i].b);

That should be all the changes you need to make, the rest should work as-is.

You can go further and make an arm struct and a step struct as well.

Upvotes: 1

Related Questions