Search

9.5 — Multidimensional Arrays

The elements of an array can be of any data type, including arrays! An array of arrays is called a multidimensional array.

Since we have 2 subscripts, this is a two-dimensional array.

In a two-dimensional array, it is convenient to think of the first (left) subscript as being the row, and the second (right) subscript as being the column. This is called row-major order. Conceptually, the above two-dimensional array is laid out as follows:

[0][0]  [0][1]  [0][2]  [0][3]  [0][4] // row 0
[1][0]  [1][1]  [1][2]  [1][3]  [1][4] // row 1
[2][0]  [2][1]  [2][2]  [2][3]  [2][4] // row 2

To access the elements of a two-dimensional array, simply use two subscripts:

Initializing two-dimensional arrays

To initialize a two-dimensional array, it is easiest to use nested braces, with each set of numbers representing a row:

Although some compilers will let you omit the inner braces, we highly recommend you include them anyway, both for readability purposes and because of the way that C++ will replace missing initializers with 0.

Two-dimensional arrays with initializer lists can omit (only) the leftmost length specification:

The compiler can do the math to figure out what the array length is. However, the following is not allowed:

Just like normal arrays, multidimensional arrays can still be initialized to 0 as follows:

Accessing elements in a two-dimensional array

Accessing all of the elements of a two-dimensional array requires two loops: one for the row, and one for the column. Since two-dimensional arrays are typically accessed row by row, the row index is typically used as the outer loop.

In C++11, for-each loops can also be used with multidimensional arrays. We’ll cover for-each loops in detail later.

Multidimensional arrays larger than two dimensions

Multidimensional arrays may be larger than two dimensions. Here is a declaration of a three-dimensional array:

Three-dimensional arrays are hard to initialize in any kind of intuitive way using initializer lists, so it’s typically better to initialize the array to 0 and explicitly assign values using nested loops.

Accessing the element of a three-dimensional array is analogous to the two-dimensional case:

A two-dimensional array example

Let’s take a look at a practical example of a two-dimensional array:

This program calculates and prints a multiplication table for all values between 1 and 9 (inclusive). Note that when printing the table, the for loops start from 1 instead of 0. This is to omit printing the 0 column and 0 row, which would just be a bunch of 0s! Here is the output:

1    2    3    4    5    6    7    8    9
2    4    6    8    10   12   14   16   18
3    6    9    12   15   18   21   24   27
4    8    12   16   20   24   28   32   36
5    10   15   20   25   30   35   40   45
6    12   18   24   30   36   42   48   54
7    14   21   28   35   42   49   56   63
8    16   24   32   40   48   56   64   72
9    18   27   36   45   54   63   72   81

Two dimensional arrays are commonly used in tile-based games, where each array element represents one tile. They’re also used in 3d computer graphics (as matrices) in order to rotate, scale, and reflect shapes.


9.6 -- C-style strings
Index
9.4 -- Sorting an array using selection sort

137 comments to 9.5 — Multidimensional Arrays

  • // Is this a good solution for 2D array example you've shown above?

    #include <iostream>

    int main()
    {
        constexpr int rows {10};
        constexpr int cols {10};
        int product [rows][cols];
        for (int r{1}; r<rows; ++r)
        {
            for(int c{1}; c<cols; ++c)
                {
                product[r][c]= r*c;
                std::cout << product[r][c] << '\t';
                }
            std::cout << '\n';
        }
        return 0;
    }

  • sk

    Hey!
    Tried doing something today. It's pretty basic. It checks if the line represented intersects another line or not. Was there a better way to do this? Also how do I practice to solve problems of increasing difficulty?

    • nascardriver

      Hi!

      > Was there a better way to do this?
      You have 1 line segment and 1 point. You're not calculating if the point is on the line segment, so I don't understand what you're trying to calculate. I can't review your math if I don't know what your goal is, so I'll just review your code

      - You're mixing types. A `bool` is `false` or `true`, nothing else. Don't assign it a string literal (Line 29), don't store it in an `int` (Line 65,70), don't treat an `int` line a `bool` (Line 72).
      - `getCoordinates()` and `getLength()` are duplicates of each other. Remove one of them, rename the other to "getInteger" or similar.
      - `getOrientation()`'s return value is magic. The caller can't know what the return value means without reading the implementation. You can fix this by returning an enumerated type. `getOrientation(axis)` is equivalent to `axis != 'y'`, so you might as well remove this function or move line 58-60` into it. You can also un-magicify the return value by renaming the function.
      - `checkLine`: You don't need a loop. Loops are expensive and should only be used if you have to. If I give you a broken off piece of a ruler, do you need to look at every single number to tell me if a given number is on there?
      - There should be a `struct` that holds a coordinate (x and y) or your coordinates should be arrays (x[2] and y[2]).

      > how do I practice to solve problems of increasing difficulty?
      Solve them as far as you can, this might take up multiple days. Then, no matter if you solved it or got stuck, look up the solution and compare it to what you did. Try to understand what the differences are and why the solution is better than your solution (Assuming the solution is better than your's).

      • sk

        Hi.
        As I have just started coding a few days ago, it's challenging for me to analyze my code optimizations so thank you.
        This program is supposed to get two coordinates and the length of first coordinate and check if the segment so formed (not the one formed by joining both) they ever intersect. The respective coordinates only form lines parallel to the axes.
        Also what would the struct look like?

        • nascardriver

          If I understand you correctly, this is
          a line segment from (5000,0) to (5001,0)
          and
          a point at (0,0)

          The point is not on the line segment, but your program says it is.

          The struct could be

    • Sahil

      This is a bit late and nascar has already pointed out nearly all the optimizations except one, in the getOriantation() switch statement you have already provided a return statement for the two cases, hence the break after each return is redundant, removing them won't optimize the performance but its not needed so removing it is a good idea.

  • shaheer

    Q: Define two arrays, one with the name of previous marks and one with the name of current marks.  Generate  the  marks  with  the rand()  function  and  with  a  check  that  it  should  not generate a number greater than 100 and less than 20 for each array. Each value generated by rand() function should be stored in the respective arrays. After  storing  the  randomly  generated  marks  in  current  array,  add  all  the  marks  in previous  array  and  in  the  current  array  separately.  Take  an  average  of  previous  array marks  and  take  an  average  of  current  array  marks  and  find  that currentmarks  are  better than previous marks or not. Note: Pass all the values as arguments to the function named Comparison.Note:

  • shaheer

    Q: Pass two one dimensional array as an arguments to a function and compare the two arrays and see of both the arrays are equal or not?

  • Hello!
    I like this site !  Very useful and informative.
    There is a problem:
    A multidimensional array is given.
    Number of rows and columns are identified by user and elements of array as well.

    There is k entered by user.
    Program should add a column after k th column with elements equal to 0.
    For example : a[2][3];
       {{1 2 3}
        {1 2 3}}
    k = 1;
    then array becomes a[2][4];
       {{1 2 0 3}
        {1 2 0 3}}
    However when I run the code some elements of array changing their values.   To understand what is going wrong you can compile my code!
    I wasn't able find what's a problem.  Please help!
    This is my code:

  • sito

    hello!
    I have some code that depends on the index of rows in an array in order to work. But i'm doing something wrong here since the row of my array is filled wwith 0's while my collumns are working just fine. Am i initialising the array the wrong way or something? the outer row shouldn't just be a bunch of 0's should it? here is an example
        int array[][2]{ {2, 2} };
    When i loop through the array i can print out my collumns so i don't know what's going on. any help would be nice

  • Ryan

    Take an array[4][4] with a 4 x 4 dimension.

    Would array[2][1] be the same as array[1 * 3 + 2], if we were to translate it back to 1D?
    array[1][3] is the same as array[3 * 4 + 1]?

  • Knight

    Hi, nascardriver and Alex,
    I do not understand about the last example:

    Why need this faction? Did the multiplication result store in the memory? Then the pint fraction load the result from the memory? And why did not need the {} brackets in multiplication fraction? Thanks.

    • S.M.Haider

      Yes;
      The prior code initializes the respective values to product[row][col] where each entry has a value e.g. product[1][1] = 1, product[1][2] = 2, ..., product[9][9] = 81. All these values allocate memory to be stored in the array and then it is printed by the above code.

  • Q

    I notice that in your multiplication table one raw (starting from 0) was wasted. I think we could use the following!

  • nascardriver

    Vectors and arrays aren't comparable. You need to tell `std::sort` how you want to compare them by giving it a comparison function. We show how to do this later in this chapter.

  • Nguyen

    The compiler can do the math to figure out what the array length is. However, the following is not allowed:

    Is it the leftmost length that the compiler can do the math to figure out?
    Is there any formula for it?

    Thanks,

  • Sahib

    I don't know if this has been mentioned before, but I think the last piece of code could be optimized by combining the for loops like this:

    If I'm doing anything wrong, please tell me.

  • Charan

    Hey,I did not see the chapters ahead, is there any chapter on how to pass two dimensional arrays as parameters to a function?This is a very confusing part in C.

    • nascardriver

      Multidimensional arrays aren't nice to work with. Use a 1-dimensional array if that's not too difficult.

      Or, I don't know if this is well-defined:

  • nascardriver

    If you change `arr[num_rows][num_col]` in line 12 and 19 to `arr[i][j]`, the program works. I suppose you forgot one of them.

    What you also should do, but is unrelated to the problem
    - Disable compiler extensions (Lesson 0.10). Line 9 is illegal. `num_rows` and `num_col` should be `constexpr`.
    - Use ++prefix unless you need postfix++, which you don't.
    - Use a code-formatter.
    - Initialize variables with brace initialization.
    - Use single quotation marks for characters ('\t' and '\n' instead of "\t" and "\n").

  • Tushar Roy

    This won't print anything to the screen

  • Abdul Hanan

    How we can initialize a 2-dimensional array with value -1. i.e. all elements of the 2-dimensional array contain value -1.

  • Benur21

    Hi. The "Calculate a multiplication table" loop could also start at 1, to avoid multiplying zeros and replacing zeros with zeros.

    Love these tutorials!

  • Barne

    Hello,

    When making my own 4-in-a-row program I struggled with passing these 2d arrays to functions. Eventually caved and just made the array size a "magic number" because thats the only thing that I could figure out. After reading this chapter I still found I didn't know how to properly pass them. Looked something like this in the end:

    Preferably I would have liked to use a reference or just write the passing statement as a pointer but I got all kinds of errors.

    Is passing a 2d array something covered in chapter 7, or is there a section I should revise in this chapter? Skimmed the chapter again and could not find any details, only stuff that worked for single arrays.

    Once again thanks to nascar and Alex, without you the program would never have worked at all, I feel pretty proud that it finally works and its all thanks to you!

    • Hi Barne!

      * You're using the same name style for types, variables, and functions. This will lead to confusion.

      > Eventually caved and just made the array size a "magic number"
      Declare constants.

      You're allowed to omit the first size specifier of multidimensional arrays, but not the others.

      > I would have liked to use a reference

      Or let the compiler do it for you

      > write the passing statement as a pointer
      The outer array would have to decay to a pointer to int[7] and the inner array would have to decay to a pointer to int. I don't think both arrays can decay at the same time. Maybe someone else knows more.

      Use a type alias, it saves you a lot of ugly syntax.

      • Barne

        Hello nascar,

        > Declare constants
        I assume you mean a global constant within a namespace since I can’t use a constant declared within main() in the parameter?

        I see your use of references, but since I still have to write out the array size I don’t think it helps me too much. Guess there is no easy way of omitting both specifiers?

        • > I assume you mean a global constant within a namespace
          Correct.

          > Guess there is no easy way of omitting both specifiers?
          Type aliases. Saves you from magic numbers and ugly syntax.

  • ASY

    How to print size of multi dimensional array?
    Because std::size(array) is not effective for multi dimensional array,
    it will only return no of rows but not the column.

  • Hi I need your help
    I did'nt get the last program can you explain it?

    • Sky

      Hi Sourabh,
      1) for (int row = 0; row < numRows; ++row)
      2)    for (int col = 0; col < numCols; ++col)
      3)        product[row][col] = row * col;

      first in the outer for loop(line no 1) we are taking row as a multiplier and in the inner for loop we are taking col as a number
      so lets skip the zero multiplier(row = 0), start with row = 1
      once row is initialize with value 1 inner for loop will start iteration.
      col will be initialized with 0, 1, 2, 3,..., 9
      and at line no 3 we are multiplying these value of col with that of row(i.e 1)
      so in this way we are storing one's table
      after that row =2 and then it will multiply col by row = 2
      and give us the two's table. similarly it will continue till row = 9.
      and then at printing the table we are excluding 0th row and 0th column because those will only contain zero.

  • tbnal

    how to initialise all elements of s fixed array from console

    • Alex

      If by console you mean user input, there's no easy way to do this. You're better off initializing to some initial value (e.g. 0) and then use a look to ask the user to provide values, and use assignment to get them into the fixed array.

  • Haider

    Hi,
    Do multidimensional arrays allocate more memory than standard arrays?

    • Hi Haider!

      The standard doesn't force a specific implementation, so there is no general answer to your question.

      Both arrays can store 10 ints.

      Assuming x86_64 architecture with sizeof(int)=4 and sizeof(void*)=8; no compiler optimization; and ignoring the compiler-generated information block:

      One way of implementing multidimensional arrays is:
      @a takes up 8 bytes for the pointer to the first element and 4 bytes for each element. 8B + (10 * 4B) = 48B

      @b takes up 8 bytes for the pointer to the first element, each sub-array takes up 8 bytes for the pointer to their first elements, and each int takes up 4 bytes. 8B + (5 * 8B) + (5 * 2 * 4B) = 88B

      Conclusion: The more sub-arrays there are, the more memory is used.

      GCC's way of implementing multidimensional arrays is:
      A multidimensional array is a one-dimensional array. All elements are stored one after the other in memory, resulting the the same memory usage as one-dimensional arrays.

  • hrmn

    This means, initialize the first elements to 1 and 2, and the rest of the elements "as if they had static storage duration". There is a rule in C saying that all objects of static storage duration, that are not explicitly initialized by the programmer, must be set to zero.

    i read this here https://stackoverflow.com/questions/15520880/initializing-entire-2d-array-with-one-value

    can you please explain this , will it mean the array indices whose default value is set 0 as if static will have file scope? and what else automatically falls into static storage duration ? and does every data type is default 0 in this storage?
    and why you didn't used {} instead of {0}?
    sorry for so many questions..
    Thanks

    • Alex

      Nope, because that's a C rule. C++ rules for initialization of arrays are here: https://en.cppreference.com/w/cpp/language/aggregate_initialization

      In particular: "If the number of initializer clauses is less than the number of members and bases (since C++17) or initializer list is completely empty, the remaining members and bases (since C++17) are initialized by their default initializers, if provided in the class definition, and otherwise (since C++14) by empty lists, in accordance with the usual list-initialization rules (which performs value-initialization for non-class types and non-aggregate classes with default constructors, and aggregate initialization for aggregates)."

      If you look up value initialization (https://en.cppreference.com/w/cpp/language/value_initialization), you'll see this: "...otherwise, the object is zero-initialized.", which is what happens here for the elements that don't have initializers specified.

  • KKR

    Can someone explain the output for the below program??

    Output:
    21
    18
    21

  • KKR

    • nascardriver

      Hi KKR!

      @Alex Do you have an explanation for why Line 8 in @KKR's code is a thing? I can't find any information about it. Probably because I don't know what to search for.

  • Will

    Hello, why when I make a multidimensional array like this
    std::array<std::array<int, 3>, 3> arr{ { { 1, 2, 3 },{ 4, 5, 6 },{ 7, 8, 9 } } }
    I cant access it as in your example std::cout << array[0][1][2]
    The last one says "Expression must have pointer to object"

    • nascardriver

      Hi Will!

      Two issues,
      1] Your array is two-dimensional (3x3), but you're trying to access it like a three-dimensional array. The deepest you can go on a two-dimensional array is arr[x][y], not arr[x][y][z].
      2] You named your variable 'arr' but you're trying the access 'array'. That's what's causing your error.

  • Micah

    Maybe it's just for education purposes, but otherwise wouldn't you keep it simple and create a "int multiply(int x, int y){}" function and just make it so "array[row][col] = multiply(row, col)"  in a for loop?

  • CuRSeD

    how can I set the value of 2d array from the user?

    int a, b;

    cout << "Enter first value :  " ;
    cin >> a ;
    cout << "Enter second value : " ;
    cin >> b ;
    // i will get error

    int myArray[a][b]

  • can we use vectors as multi-dimensional arrays?
    if yes, how?

    • Alex

      You could have a vector of vectors. But you're maybe better off allocating a single dimensional vector and use math to map two coordinates down to one.

      • Nguyen

        Hi,

        For multi-dimensional vector arrays, how can I determine the left length in line 16 and right length in line 17 in the program shown below?

        • nascardriver

          You have to make sure that `leftLength` is non-zero before accessing array[0] to get `rightLength`.

          Note though that all inner vectors can have different lengths. If you need all of them to have 2 elements, use `std::vector>` instead.

          • Nguyen

            Thanks nascardriver,

            Looks like the leftLength and rightLength no longer work for this example?  What are they?

          • Nguyen

            Thanks nascardriver,

            Just wondering if you have any "magical" formula for sort I can add to the program in line 18?
            I tried std::sort(begin(array), end(array)), but it does not work.

            • nascardriver

              Please use the edit function instead of deleting and re-posting. My reply is here https://www.learncpp.com/cpp-tutorial/65-multidimensional-arrays/comment-page-2/#comment-465389

Leave a Comment

Put all code inside code tags: [code]your code here[/code]