6.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:

Note that this only works if you explicitly declare the length of the array! Otherwise, you will get a two-dimensional array with 1 row.

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.

6.6 -- C-style strings
6.4 -- Sorting an array using selection sort

64 comments to 6.5 — Multidimensional Arrays

  • Soumil

    I didn’t understand how the formatting of the multiplication table works. The program outputs a tab after each array element, so shouldn’t an element after a double-digit number be off by one space?
    1    2    3    4    5    6    7    8    9
    2    4    6    8    10   12   14   16   18
    In the second row, 12 aligns perfectly with the 6 in the first row, whereas I expected it to be off by one space.

    • Alex

      Nope. Tabs jump the cursor to the next tab stop (which console applications usually set 8 characters apart).


      In the top example, if we’ve printed the number 1, and then do a tab, the tab will jump past 7 x’s and end up at character t.
      In the bottom example, if we’ve printed the number 123, and then do a tab, the tab will jump past 5 x’s and end up at character t.

      This makes it easy to align data values of different lengths so long as the length of the data doesn’t exceed the length between tab stops.

  • Ville-Pekka

    Hi Alex,

    Why do these two pieces of code work differently? In my mind, they seem like they should do the exact same thing.

    The code above works as it should. It adds the line break after a certain amount of columns. Nothing wrong there.

    Now this one does the same thing and it works, technically, but it adds a lot more than 1 line break when placed in the exact same spot as the previous code.

    Here’s the function as it works:

    • Alex

      Neither of these really work “correctly” -- the former ends up producing the result you want, but in a way that’s more complicated than it needs to be.

      You can replace this:

      with this:

      Much simpler, yes?

  • Pixel

    hey alex!
    u ve created an amazing tutorial! its really helping me a lot! thank you!

    i have a doubt-
    if we initialize a char array with int values n then try to print any element of that char array, what would actually happen?
    i mean a code something like this one-

    when i try to run it, it displays a wierd character inside a box.

    • Alex

      Chars are treated as ints in C++, they just _print_ as ASCII characters. So in the above case, you’re printing the ASCII characters 1, 2, 3, 4, and 5, which are non-printable characters, so your console is assigning some symbol to them.

      If you try this:

  • Slayther

    "Because the inner parenthesis are ignored, the compiler can not tell whether you intend to declare a 1×8, 2×4, 4×2, or 8×1 array in this case."

    How are inner parenthesis ignored? If they were ignored, I wouldn’t be able to do this:

    And have correct initialization of missing elements to 0. Or am I missing something?

  • Matthieu B.

    Yet another unimportant correction, in the last sentence of the lesson:

    "They’re also commonly in 3d computer graphics (as matrices) in order to rotate, scale, and reflect shapes."

    "commonly" should either be replaced by "common" or it should be followed by "used".

  • Wojciech Pawlik

    Thank you for this amazing tutorial and exceptionally helpful support. 10/10 would recommend to a friend. Very fine work.

  • Nyap

    I’m making a tictactoe game but I’m too lazy to finish the AI
    I have a basic idea of how I want it to work though
    Might need some better code organization aswell

    Also, am I the only one who finds working with arrays confusing? I understand them well, but when I come back to a piece of code I’ve written that uses them I find myself re-reading all the code

    • Alex

      > but when I come back to a piece of code I’ve written that uses them I find myself re-reading all the code

      That could be indicative of needing either better documentation describing what your code is doing, or some refactoring to break your code down into smaller, more intuitive chunks.

  • Muhammad Kamal

    Hello Alex, you said that the compiler ignores the inner braces within the initializer list… However, I tried this out and it seems like, using Visual Studio 2015 Enterprise, those braces are actually meaningful to the compiler, as for the code:

    The output was:

    [0][0] = 1 [0][1] = 2 [0][2] = 3 [0][3] = 0
    [1][0] = 1 [1][1] = 2 [1][2] = 3 [1][3] = 4
    [2][0] = 1 [2][1] = 2 [2][2] = 0 [2][3] = 0
    [3][0] = 1 [3][1] = 2 [3][2] = 3 [3][3] = 0
    [4][0] = 1 [4][1] = 2 [4][2] = 3 [4][3] = 4
    Press any key to continue . . .

    Feeling a bit confused and frustrated, because I just answered in a CS exam today based on what you wrote…

    • Alex

      Yes, my initial wording was poor, as I was talking just about the behavior when all initializers are accounted for. I’ve updated the article to show what the behavior is with missing initializers, and how the inner braces do matter in that case. My apologies for misleading you.

    • Muhammad Kamal

      Also downloaded Code::Blocks and tested using g++, yields same result. 🙁

      Dunno if this "ignoring" issue was before C++11 or you got it wrong… Or you knew it well, but couldn’t convey the idea well… But I wouldn’t want anyone to fall for this like me!

      • Muhammad Kamal

        Apology accepted. 🙂 (Didn’t see your reply before posting my last reply (that’s the whole purpose of this reply actually xD))

  • Shiva

    Hi Alex, a couple of things occurred to me (if they are on purpose, please ignore) :

    #1 The ending comma within each inner list (except the last one of course) in the initialiser list seems redundant, as these lists themselves are followed by commas. Once the braces are ignored, those last-column elements are followed by two commas. The compiler may handle this well, nevertheless it feels a bit awkward. IMHO removing those commas and using proper indentation improves consistency as well as readability:

    #2 Below ‘Accessing elements in a two-dimensional array’, you suddenly talk about for-each loop which you have not covered yet. Seems like you put it in the wrong place. We got a for-each only lesson later, haven’t we?

    • Alex

      The trailing inner commas were a typo. I’ve updated the example.

      Thanks for the note about the for-each loops. I moved that lesson to a later point where it made more sense (after references), and forgot to address it here. I’ve updated the lesson to just make note that you can do so, without the details of how (since we haven’t covered the concept yet).

      • Shiva

        Great! What about giving indentation to the inner lists? Is there any reason not to?

        Another thing I’d like to mention, initialising a multi-dimensional array to 0 with single braces gives a compiler warning:
        int array[3][5] = { 0 };
        // warning: suggest braces around initialization of subobject [-Wmissing-braces]
        //  int a[3][3] = { 0 };
        //                      ^
        //                      {}
        Some readers have already pointed this out. Not likely an issue, just mentioned.

        *off-topic Alex, is there any way we could get an email notification when we get a reply to our comments? Can make life a bit easier.. 🙂

        • Alex

          You can indent in whatever way you think is most readable. The compiler doesn’t care about whitespace.

          Some compilers may complain about the above as you note. If yours does, you can use a brace for each dimension

          I’ll try to see if there’s a plugin to send out an email notification. That seems valuable.

        • Shiva

          Indeed. That would be great. Tell us if you find a way.

          Thanks for the tips too! 🙂

  • Elpidius

    Hey Alex, above you wrote:
    "Three-dimensional arrays are hard to initialize in any kind of intuitive way using initializer lists…". However, it is possible to initialize a three-dimensional array using an initializer list.

    You also mentioned: "when the C++ compiler processes this initializer list, it actually ignores the inner braces altogether. However, we highly recommend you use them anyway for readability purposes."

    I agree with what you’ve said. Older compilers used to give warnings about leaving out the nested braces. As such it is good to get in the habit of using a set of braces, one for each dimension of the array.

    In a three-dimensional array we need three sets of braces:

    A clearer example might be:

    As you can see, the third dimension is called a "layer", and is also called a sheet (as in Excel), or page.

    In order to print the aforementioned array, we just use three loops: one for the layer, one for the row, and one for the column.

    Conceptually, the above three-dimensional array is laid out as follows:

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

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


  • Nortski

    Question: Based on all the tutorials up to and including this one, would it be possible to develop a very simple minesweeper clone game?

    • Alex

      Almost. The major thing you’d be missing is the graphical output and input. Minesweeper shows on a graphical grid, and you can click a cell with a mouse to uncover it. Both of those things are outside the scope of these tutorials (currently), as you’ll have to use a 3rd party library (like SDL) to do that.

  • What a great tutorial, thanks buddy for sharing this information with us

  • Quang

    In the last example , u forgot to use namespace std therefore the code couldn’t run, Alex !!!

  • I was trying to sort a two dimensional array:

    The problem with this program is that it sorts the elements of 1 array and prints result. I want it to sort the entire array. I mean, I want to scan through all the arrays to get the smallest element and print this at first place. I want something like: 1 1 2 2 2 3 3 3 4 5 6 6 6 7 7 7 7 8 8 8 8 9 9 9 9
    Please suggest some edits in the above code. Thanks…

    • Alex

      So it looks like you’re locally sorting each array, and then printing out each array in order.

      With these sorts of problems, it’s often better to step away from the code and decide what you want to do at a theoretical level first, then implement it. As I see it, you have a few choices:
      1) Sort each array locally (like you are now), and then use logic to determine which value from which array to show next. This would involve keeping a pointer or index to each array, and comparing the lowest non-printed value of each array to determine which one to print next. Seems messy.
      2) Treat all of the arrays as a single array, sort across all the arrays, and then print in order. In this case, building a function to treat your arrays as if they were a single contiguous array might be helpful.
      3) Combine all of the arrays into a single one-dimensional array, then sort the single array. Will use more memory, but way simpler.

  • C++ newbie

    Wow, that explanation was great help.  Thanks !

  • Peter

    In the first example you have

    but then the layout is I think for  

  • Snowman

    I’m up to chapter 7 and decided to play around a little, so I made Tic Tac Toe. It’s player vs player (no CPU yet) and very stable. Took 2 or 3 lines off Google purely for incorrect inputs. I’m no where near a professional programmer, so be kind! =P

    Select a number from 1-9 (read left to right) to play. X’s go first


    Website is bugging out with text between less than and greater than signs. Code can be found here:

  • Fred

    OK so a two dimensional array is an array of arrays where each row is an array.

    Does a 2D array have to be rectangular. That is, does each row have to have the same number of elements?

    • Alex

      A two-dimensional fixed array will always be rectangular, because you can only specify the number of column and rows.

      A two-dimensional dynamic array does not have to be rectangular because you have control of the memory allocation yourself and can make each row a different length.

  • Michael

    Hello Alex!

    Thx for the great site! I am already recommending it to my friends 🙂

    Question about arrays - how big can they get?

    In the code below, I use "const long ArraySize = 1000000;" to define the size of my array.

    I defined an array of random numbers that had 100 000 elements and my code runs fine.
    When I increased the size to 1 000 000 elements I get a ‘stack overflow’ message.

    "Unhandled exception at 0x00A930B7 in brudnopis.exe: 0xC00000FD: Stack overflow (parameters: 0x00000000, 0x00282000)."

    Using Windows 7 and MS VS 2013 Express.

    This is just prototyping. I would like to use arrays of structs with up to 10 million elements in the future for modelling.

    Any suggestions?

    PS. I have 16 GB of RAM memory and an i7 Intel processor; waitforuserend() is in another source file - it’s the code you posted at the start of this tutorial. The two commented out lines of code stay commented out when I compile.

    • Alex

      I think Visual Studio sets the stack size to 1MB by default. There should be a compiler option to increase this.

      That said, for something so large, I’d probably look to allocate the memory dynamically instead of statically.

      • Michael

        I wish MS help websites were better…..
        Took me half an hour to figure out how to increase stack size….
        Project -> Properties -> Configuration Properties -> Linker -> System -> Stack Reserve Size

        Set it to 200000000 (around 200 MB i guess?)
        Now my code will run even if I set the ArraySize to 25 million. Takes it 22 seconds to complete.

        I hope I will learn how to ‘allocate memory dynamically’ later on.

        Thanks for your help!

  • I.P

    Hi, thanks for the great tutorial.
    Following the tutorial, I’v been trying to make vertex-4 coloring code.
    I’m stuck here: vertexColoring[the number of colored maps][the number of whole nodes]
    So, each row stands for one colored map.
    But the problem is that the size of row is an exponential function of the size of column. and It seems the size of this array gets to a limitation very quickly.
    Is there any solution for this? (certainly though, because vertex coloring is one of the computer-science subjects)

    • Alex

      If you’re running out of memory allocating large fixed arrays, move to allocating your arrays dynamically. Dynamic arrays can be much larger before running out of memory.

  • ProgrammerJupiter

    anArray[2][3] = 7;

    int anArray[3][5] =
    { 1, 2, 3, 4, 5, }, // row 0
    { 6, 7, 8, 9, 10, }, // row 1
    { 11, 12, 13, 14, 15 } // row 2

    Just curious wouldnt anArray[2][3] = 14? if i am understanding how this works properly

  • Adi_ida

    How to convert an array of 2 dimensions to one dimension?

    • Most of the time that question will be mostly academic albeit interesting, as this is most likely how the memory layout will be designed. However I cannot recall ever having the need to actually do that conversion. But let’s write two 2 dimensional arrays out, where all the fields are numbered in increasing order. Let’s write a 3×3 array first:

      0 1 2
      3 4 5
      6 7 8

      Then 5×4

      0  1  2  3
      4  5  6  7
      8  9 10 11
      12 13 14 15
      16 17 18 19

      Now if you look carefully at the first columns, you may be able to see a pattern. If we name the current row r, and let i start at 0, just like we index arrays, then you can actually calculate these numbers as a factor of the number of columns. To calculate the first number in a row it will start with r*nNumCols, which in turn for the first row gives 0 (as r starts at 0) then you’ll have (r=1) 4 (1*4) and 3 (1*3) respectively and so on.

      Now the observant reader may have noticed that the "r" I introduced is actually exactly the nRow used in the code in the guide.

      To calculate the exact number you also need to add something, but if you take a look at nCol in the examples above this will exactly be the offset needed to be added. So the entire formula will be nRow*nNumCols+nCol (notice that nCol will restart at 0 each iteration and will max be nNumCols-1).

      So actually you can just transform an 2 dimensional array into a 1 dimensional by having the size as nNumRow*nNumCols. Another thing to notice is that the uneeded { and } for multiple dimensions this actually corresponds exactly to this.

      Now to relate that to how the memory maps this. Say we use int32_t as our type for an array. We know from previous lessons that this corresponds to exactly 4 bytes. The way the memory works is that it knows where the array starts, lets call it position A. If the array starts at A the first element will be in the 4 bytes starting at A, the next will be at A+4, and the next as A+8 and so on. The numbers will change according to the data type in use. The formula for the memory will then be A+4*offset where offset is our formula above, so A+4*(nRow*nNumCols+nCol). Then of course we could replace 4 with the size of our type.

      One disclaimer most memory models (as far as I’m aware, bear with me, it’s a long time since I had this) actually index from high memory addresses to low ones, so actually it would be A-4*…, but for understanding this doesn’t matter, and I do believe it’s easier to visualize it increasing in stead of decreasing.

  • DaMonroe

    Great, but if you don’t know the length of the actual number of rows, the outer loop can’t be a “for” loop. How could a “while” be controlled when filling an array from a file?

    • copier1

      Arrays have to be initialized with the dimension size. In a later lesson you learn how to do this at run time instead of at the time it’s compiled. In either case, the size does have to be dimensions do have to be known beforehand.

      You can use a function or a class to determine the length and number of rows from the file.

    • Alex

      If you don’t know the actual number of rows before reading in a file, you have a couple of options:
      1) Do two passes on the file. The first to establish the size of the array needed, and the second to actually read the data in.
      2) Read the data in as a single-dimensional array and then convert to a two-dimensional array once you know the size.

  • I will give two kinds of methods (one is similar to the author’s, but a bit shorter)

    The first method just takes the cout into the loop as well.
    The second is just the stupid-way to do this problem, using additional instead.

  • Cheesefriend

    using a 2 dimensional array that is printed to the screen
    is properly the eaisest way to make a 2d game map you
    can move around on for those that is intrested in that.

    made a game like that in matlab:)

  • Kevin

    g++ compiler required double { { } } braces as follows compared to the single in the example

    • ca336458

      g++ didn’t require it for me as an error, just gave me a warning when using just the one set of braces. That warning went away when I used 2: int nProduct[nNumRows ][nNumCols ] = {{ 0 }};

  • Peter LaBanca

    For optimization purposes, so you don’t have to repeat the loops twice creating redundancy, isn’t it better to compact the code from:


    With processors nowadays I am sure that won’t impact performance that much but every bit counts, especially with bigger, more complex programs.

    Peter LaBanca

    • In the real world I would have combined the two loops for efficiency reasons. Here, I did not because I thought it made for a cleaner, easier to follow example.

    • dex

      Hi Peter,

      I’m just wondering, instead of having if condition to remove 0, why not set nRow and nCol to 1?  

  • Rajesh

    Can you just explain how the 2d arrrany multiplications are done?
    and also sorting of string values using array?

    • I am not sure what you mean by “2d array multiplications”.

      As for using arrays to hold strings, that’s covered in the very next lesson on C-style strings

      • J3ANP3T3R

        can i create a 2 dimensional array with two different data types ? like 3 enum class arrays each containing 4 integer values ?

        • Alex

          Not really. C++ doesn’t have direct support for arrays containing different types of data. There are a few ways to work around this, but none of them are great.

    • I expect what is meant is matrix multiplication, however that is a topic of maths rather than programming to begin with, later on algorithms though for efficiency. But even the second part is way out of scope for a book on how to use a language. If Rajesh or anyone reading is curious on the topic, I suggest learning the maths first (I do believe KhanAcademy has lessons on linear algebra) and then go read about algorithms.

    • Muhammad Faizan

      using namespace std;
      int main()
              int i,j,k,l,r1,r2,r3,c1,c2,c3;
              cout<<"For finding the Multiplication of the Two Matrices, You have to Enter the values that I mentioned below;\nFor Multiplication, the Number of Coloumns of 1st Matrix should be Equal to the Number of Rows of the 2nd Matrix\nSo, you should Enter    c1=r2 .\n\n\n";
              cout<<"Enter the Number of Rows of a[] which is [r1] : ";
              cout<<"\n\nEnter the Number of Coloumns of a[] which is [c1] : ";
              cout<<"\n\nEnter the Number of Rows of b[] which is [r2] : ";
              cout<<"\n\nEnter the Number of Coloumns of b[] which is [c2] : ";
                  int a[r1][c1],b[r2][c2],c[r1][c2];
                          cout<<"Enter the value number a["<<i<<"]["<<j<<"] : ";
                              cout<<"Enter the value number b["<<i<<"]["<<j<<"] : ";
                      cout<<"\n\nMatrix form of a["<<r1<<"]["<<c1<<"] is given below;\n\n";
                          cout<<a[i][j]<<"   ";
                      cout<<"\n\nMatrix form of b["<<r2<<"]["<<c2<<"] is given below;\n\n";
                          cout<<b[i][j]<<"   ";
                      cout<<"The matrices which are a["<<r1<<"]["<<c1<<"] and b["<<r2<<"]["<<c2<<"],\nTheir Multiplication is given below;\n\n";
                                      cout<<c[i][j]<<"   ";
                  cout<<"\n\n\n\n\n\nYou have entered the different values of c1 and r2;\n\nPlease enter the same values of both c1 and r2\n\n\n\n\n";
                  goto again;

Leave a Comment

Put C++ code inside [code][/code] tags to use the syntax highlighter