Source: https://mokxi.com/learn/arduino-2d-array
Updated: 2026-10-25

Learn

# Arduino 2D arrays, on a die drawn on an 8x8 matrix

Intermediate

Written by the Mokxi team, updated October 25, 2026

Start building free Open the editor

Or see every lesson.

- 455 parts on the bench
- 43 boards running now
- 1.00x real time, on every board

Press Run, then click the tilt switch a few times

Click the tilt switch to shake it. Each face is one row of FACES, eight bytes for eight lines of LEDs.

A two-dimensional array is a table. int grid[3][4]; is 3 rows of 4 numbers each, and grid[1][2] is row 1, column 2, both counted from 0. To go over the whole table, put one for loop inside another: the outer one for the rows and the inner one for the columns.

The circuit above is a die on an 8x8 LED matrix on an Uno. Its sketch keeps all six faces in const byte FACES[6][8]: six rows, one per face, of eight bytes, one per line of LEDs. Press Run and click the tilt switch a few times to shake it. The face rolls, slows and stops, the RGB LED turns green, and the serial monitor prints "rolled a" and the number.

Below is the dice table, making and filling a grid, counting rows and columns, passing a table to a function, a table of words, and what a big table costs on an Uno, each run with what it printed.

## Six faces, eight rows each

Here is the table from the sketch running above and the function that draws a face. FACES[n - 1] is the whole face for the number n, and FACES[n - 1][row] is one line of it, a byte whose bits are the eight LEDs across. The face for 1 is all zeros but rows 3 and 4, where 0x18 lights the two middle LEDs: the single pip.

firmware/uno/examples/kcdice (the faces running above)

## Make one, fill it, print it

Each inner pair of braces is one row. The sketch below prints the grid as a table, one row per line with a tab between the numbers, and then grid[1][2], which printed 7: row 1 is the second row, and column 2 is its third number.

Writing works the same way as reading: grid[row][col] = value; inside the same two loops fills the whole table, row by row. Keep the rows on the outside and the columns on the inside, because that is the order the numbers sit in memory, and use names like row and col rather than i and j, so a swapped pair of indexes stands out when you read it back.

A 3 by 4 grid

## How many rows and columns

sizeof(grid) is the size of the whole table in bytes: 24 for 12 ints of 2 bytes. Divide by the size of one row, sizeof(grid[0]), for the number of rows, which printed 3, and divide one row by one element, sizeof(grid[0]) / sizeof(grid[0][0]), for the columns, which printed 4. Loops written with these keep working when the table grows.

The numbers sit in memory one row after another. Read past the end of a row and you get the start of the next: grid[1][4] printed 9, the first number of row 2, with only a warning, array index 4 is past the end of the array (that has type 'int[4]'). Past the end of the last row there is no next row, just whatever else is in memory.

## Passing a table to a function

A function that takes a 2D array has to be told how long a row is, so it can find row 2. Only the number of rows may be left out. The sketch below adds up the grid and printed 78. Write int g[][] with both sizes left out and the build stops with array has incomplete element type 'int[]'; GCC says declaration of 'g' as multidimensional array must have bounds for all dimensions except the first.

The column count goes in the parameter

## A table of words

Text can be stored two ways. char words[3][6] is a real 2D array: three rows of six characters, each word padded out, 18 bytes in all, and words[1][0] is the letter g. const char *names[] is an array of pointers, each to a word of its own length. Both printed "green" and "blue" the same way.

A row must have room for the longest word and its zero byte. With rows of 5, "green" did not fit: initializer-string for char array is too long, array size is 5 but initializer has size 6 (including the null terminating character). GCC says initializer-string for 'char [5]' is too long.

Two ways to keep three words

## Big tables and 2 KB of RAM

An Uno has 2048 bytes of RAM for every variable in the sketch. int big[30][40] wants 2400 of them, and the build stopped: global variables do not fit in the 2 KB SRAM, overflowed by 538 bytes, counting the other variables a sketch always has. A table that never changes, like the dice faces or a font, can live in flash instead: add PROGMEM and read it with pgm_read_byte(&FACES[1][2]), which printed 6 from a small table. Flash has 32 KB.

## Questions

How do I declare a 2D array in Arduino?

Give the rows, then the columns: int grid[3][4]; or fill it as you declare it, one pair of braces per row. The row count may be left out when every row is written out.

How do I loop through a 2D array?

Put a for loop over the columns inside a for loop over the rows and read grid[row][col]. Work the counts out with sizeof so the loops follow the table if it changes.

How do I pass a 2D array to a function?

Write the column count in the parameter, int g[][4], and pass the row count as a second parameter. Only the first size may be left empty.

How do I make an array of strings on Arduino?

Use const char *names[] = {"red", "green"}; for fixed words, or a char array with one row per word, char words[3][6], when the words have to change. Each row needs one extra byte for the zero at the end.

How big can an array be on an Arduino Uno?

Everything in RAM has to fit in 2048 bytes, with room left for the stack. A constant table can go in the 32 KB of flash with PROGMEM.

Related

## Keep going

Arduino Array: Lists of Pins, Patterns and Notes Arduino for Loop: Count, Repeat, Chase LEDs Arduino MAX7219 8x8 LED Matrix: Wiring and Code Arduino Pointers Explained: & and * on an Uno Arduino "Low Memory Available" and "Sketch Too Big" Arduino String: Join, Compare, Convert, Split The tilt dice project Intermediate The free Arduino simulator The project page, with the full sketch Intermediate

Sources

## Where the facts on this page come from

- Arduino reference: arrays
- Arduino reference: PROGMEM

## Build this for real

Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.

Start building free Open the editor
