Question about Arrays.

So, I learned about arrays on the Arduino. I understand how they work, but I was looking at an example in the keypad library, and I saw that there was an array, and it had 3 arrays in it. It looks like this:

char keys[ROWS][COLS] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}
};

How does this work? Why are there 2 bracket things instead of only 1? Are these sub arrays? Please explain to me how this works! Also, about the brackets, I was told that you can put the amount of things that are going to have in the array in the brackets, but it wasn't necessary because the Arduino could count them. Is there ever a situation where you would need to put a number in those brackets? in the example, the rows and columns go in the brackets, but is that necessary?

What you have there is a two-dimension array. Essentially it is an array of arrays.

You have an array of ROWS arrays, and each of those arrays has COLS chars.

The double brackes are, yes, the sub-arrays.

If you have a single flat array then it's possible for the compiler to work out what size it is. However, if you have an array of arrays, then it needs some clues as to what the dimensions are. For example, in your snippet, there are 12 elements in total. These use 12 consecutive bytes in memory, which is fine for the compiler. But the compiler can't know that they are arranged in a 3x4 matrix without you providing the numbers.

Thank you for explaining! I am still kind of confused though... I don't get why the compiler cant just count all of the 12 objects. Is it because the name of the sub arrays isn't there? Sorry I didn't ask that well... But could you leave the first set of brackets empty since it can still count the number of arrays that are in the main array? Is that right?

Whats with the mixing of single and double quotation marks within each set of parentheses?

They're all single quotes. Comma is just a really narrow character in proportional fonts.

But could you leave the first set of brackets empty since it can still count the number of arrays that are in the main array? Is that right?

No.
In effect that would be a single dimension array in which case don't bother with second set of brackets, nor the extra curly braces. It depends exactly what you want to do with it.
so you could say

pressed = keys[rowDetected][columnDetected];  // using a 2D array

or

pressed = keys[ (rowDetected * number_of_columns) + columnDetected ]; // using a 1D array

It used to be the case that your array in the first post could be declared as

char keys[][COLS] = {
   {'1','2','3'},
   {'4','5','6'},
   {'7','8','9'},
   {'*','0','#'}
};

because the compiler could figure the first dimension out. I'm not sure if this is still legal. Anyway, it doesn't make much sense
to do it, if you know what the dimension is, unless you are trying to confuse someone looking at your code.

michinyon:
It used to be the case that your array in the first post could be declared as

char keys[][COLS] = {

{'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
};




because the compiler could figure the first dimension out. I'm not sure if this is still legal. Anyway, it doesn't make much sense
to do it, if you know what the dimension is, unless you are trying to confuse someone looking at your code.

Its correct, its also valid for array types in function parameter lists. Its because the compiler only needs to know the last dimension to be able to traverse a whole array ( more than one dimension ). This also means Its valid to pass arrays that only have a unique size on the last dimension to the same prototype.

Consider this example:

char a[][4] = {
  { 'a', 'a', 'a', 0 },
  { 'b', 'b', 'b', 0 },
  { 'c', 'c', 'c', 0 },
  { 'd', 'd', 'd', 0 },
};

char b[][4] = {
  { 'e', 'e', 'e', 0 },
  { 'f', 'f', 'f', 0 },
  { 'g', 'g', 'g', 0 },
};

void foo( char Arr[][4], int inner )
  {
    int temp = inner - 1;
    while( --inner >= 0 ){
      Serial.println( Arr[ temp - inner ] ); 
    }
  }

void setup() {
  Serial.begin( 9600 );
  foo( a, 4 );
  foo( b, 3 );
}

void loop() {}

The template version of this function is even better as it provides the actual missing values. However it probably still has the same overhead as hard coding each value ( overloading for different lengths )

EDIT: the template version proved to be better equal with a small test ( not thorough ).