Home / Computer Science / Data Structures / 2D Array Index (Row-Major Order)

Formula & Calculator

2D Array Index (Row-Major Order)

Most programming languages store 2D arrays as one long block of memory in row-major order: row by row. This formula converts a (row, column) coordinate into a single flat index: index = row × num_columns + column. For example, in a 3-column array, position (2, 1) is index 2×3+1 = 7. Understanding this is crucial for performance tuning, image processing, and interfacing with hardware or languages that use column-major order, like Fortran and MATLAB.

Computer Science Data Structures Memory Layout
VORZEP · DATA STRUCTURES & MEMORY LAYOUT TOOLS

2D Array Index Calculator

Convert between 2D coordinates (row, column) and the 1D flat index in row-major order. Solve for the flat index, row, column, or number of columns given any three of the four quantities.

index = row · num_cols + column · row = ⌊index / num_cols⌋ · col = index mod num_cols
Show as result
Row (r) Zero-indexed row of the element. 0 is the first row, 1 is the second, and so on. In row-major order, rows are stored one after another in memory.
row
r = 2 · offset from row start = 2 · 4 = 8
Column (c) Zero-indexed column within the row. 0 is the first column, 1 the second, up to num_cols − 1. Column indices restart at 0 for every row.
column
c = 3 · must be in [0, C−1] = [0, 3]
Number of Columns (C) Total width of the 2D array — how many columns each row has. This is the stride between consecutive rows in the flat layout. All rows have the same width in a rectangular 2D array.
columns
C = 4 · valid columns: 0, 1, 2, 3
Flat Index (i) Zero-indexed position of the element in the 1D flat array. In row-major order, index = row · num_cols + column. The first element is index 0, the last is index (num_rows · num_cols − 1).
index
i = 11 · row = ⌊11 / 4⌋ = 2 · col = 11 mod 4 = 3
Edit any field — the others stay in sync via index = row · num_cols + column.
FLAT INDEX (i)
11
r = 2 · c = 3 · C = 4 · i = 11
VALID COORDINATES
i = r · C + c = 2 · 4 + 3 = 11
Step-by-step solution
Flat index vs (row, column)
Flat index i Current element
Flat index grid — row by row
Flat index at each cell Current element
Sensitivity
Companion metrics
2D array — row-major layout map
Regular cell Current element (r, c) Row boundary Flat index (row-major)
What row-major indexing really measures
r · Crow offset
+
ccolumn offset
=
iflat index

Rows first, then columns

Row-major order (used by C, C++, Java, C#, Python's NumPy by default) stores the first row completely, then the second row, then the third, and so on. The flat index of an element is the number of elements that come before it: r full rows of C elements each, plus c elements in the current row. That is exactly r · C + c.

Cache-friendly for row scans

Because consecutive elements in a row are adjacent in memory, iterating a row of a row-major array touches consecutive addresses — the CPU prefetcher loves it. Iterating a column requires striding by C bytes per access, which misses the cache on every step. This is why the loop order for r: for c: is dramatically faster than for c: for r: on row-major arrays, even though both compute the same thing.

Column-major is the mirror

Column-major order (used by Fortran, MATLAB, and Julia, and by BLAS/LAPACK under the hood) stores columns first. Its formula is index = c · R + r, where R is the number of rows. The two orders give the same element set but different flat indices. Which one is "correct" depends entirely on the language and library you are using — the same (r, c) can have completely different indices in C and Fortran.

The inverse formula is exact

Given the flat index i and the number of columns C, you can recover the row and column exactly with integer arithmetic: row = ⌊i / C⌋ and column = i mod C. This works for any size array and any valid index. It is the basis for converting between flat and 2D layouts in memory-mapped files, GPU kernels, and serialization formats.

How to Use This Calculator

Enter any three of the four quantities — row, column, number of columns, or flat index — and the calculator computes the fourth via the row-major formula.

1. Edit any field

Change row, column, number of columns, or flat index. The other three update automatically using index = r · C + c and its inverse r = ⌊i / C⌋, c = i mod C.

2. Use realistic presets

Presets cover common values: rows and columns from 0 to 10, num_cols from 2 to 64, and flat indices covering the first few elements up to 100.

3. Read the result and verdict

The result card shows the featured value plus a validity check — whether the current (r, c) fits within the C-wide rows and whether the flat index is in range.

4. Inspect the layout map

The 2D grid diagram shows the flat index of every cell, with the current element highlighted. You can see exactly how row-major order assigns increasing indices left-to-right, top-to-bottom.

5. Check the charts

The first chart shows flat index vs (row, column) position. Advanced mode adds a full flat-index grid — a heat-map style view of how indices are laid out in memory.

6. Switch to Advanced for depth

Advanced mode adds the flat-index grid chart, sensitivity checks, and companion metrics including the memory address of the current element, the byte offset, and the equivalent column-major index for comparison.

What This Tool Offers

Built around the row-major formula index = row · num_cols + column — the standard way C, C++, Java, and most modern languages store 2D arrays in flat memory.

Four-way sync

Edit row, column, num_cols, or flat index — the other three update instantly. Both directions work (forward and inverse formulas).

2D layout map

A visual grid showing the flat index of every cell, with the current element highlighted, and clear row boundaries.

Validity verdict

Each result is checked for out-of-range coordinates (column beyond C−1) and negative or excessive indices, with a clear badge.

Multi-curve charts

Flat index vs position, plus a heat-map grid chart showing how indices are laid out across all cells.

Byte-level metrics

Memory address and byte offset of the current element, plus the column-major equivalent index for direct comparison.

Reference tables

Full flat-index lookup for a sample array, row-major vs column-major comparison, and a variable reference.

Reference Tables & Conversions

A 4-way converter, a lookup table of flat indices for a sample array, and a row-major vs column-major comparison.

4-way converter

row
column
columns
index
r = 2 · c = 3 · C = 4 · i = 11 · row-major

Flat Index Lookup — 4 × 4 Array

Row-major flat indices for every cell in a 4-column, 4-row array. The same layout shown in the diagram above, as a table.

(r, c)Flat index iByte offset (4 B int)Column-major i

Row-Major vs Column-Major

Same 3×4 array, two different memory layouts. The flat indices are very different.

Element (r, c)Row-major indexColumn-major indexDifference
(0, 0)000
(0, 1)13−2
(0, 2)26−4
(1, 0)41+3
(1, 1)54+1
(1, 2)67−1
(2, 0)82+6
(2, 2)108+2

Variable Reference

SymbolMeaningTypical rangeFormula (row-major)
rRow index (0-based)0 – 10⁹⌊i / C⌋
cColumn index (0-based)0 – 10⁹i mod C
CNumber of columns1 – 10⁹stride / element size
RNumber of rows1 – 10⁹total / C
iFlat index (row-major)0 – 10¹⁵r · C + c
icol-majorFlat index (column-major)0 – 10¹⁵c · R + r
bytesByte offset in memory0 – 10¹⁶i · sizeof(element)

What Does index = row · num_cols + column Measure?

The formula gives the position of an element in a flat, 1-dimensional array that represents a 2D grid. It is the bridge between the mental model of a 2D table (rows and columns) and the physical layout of memory (a single contiguous block of bytes). Every language and library that supports 2D arrays uses one of the two layout conventions — row-major or column-major — and the formula encodes exactly which one.

The Row-Major Index Formula

In row-major order the array is stored as consecutive rows: row 0 completely, then row 1, then row 2, and so on. To find the flat index of element (r, c):

index = r · num_cols + c

The r · num_cols term counts how many complete rows precede the target row, and c counts how many elements come before the target inside its own row. The inverse formulas recover (r, c) from the flat index:

row = ⌊index / num_cols⌋
column = index mod num_cols

For column-major order (Fortran, MATLAB, Julia), the roles are swapped:

indexcol-major = c · num_rows + r

Row-Major Variables

SymbolMeaningNotes
rRow index0-based; 0 is the first row
cColumn index0-based; 0 is the first column
CNumber of columnsThe stride between consecutive rows
RNumber of rowsUsed only for column-major formulas
iFlat index0 to R·C − 1 for a full array

Why the Layout Matters

Row-major and column-major give the same set of elements but completely different flat indices. The same (r, c) = (1, 2) is index 6 in a 4-column row-major array but index 9 in a 3-row column-major array. Every serialization format, memory-mapped file, GPU memory access pattern, and interop boundary between languages has to specify which convention it uses.

The layout also determines cache performance. In row-major order, iterating along a row touches consecutive addresses — the CPU prefetcher streams the data in quickly. Iterating along a column jumps by C elements (or C · sizeof(element) bytes) per step, missing the cache on every access. This is why the loop order matters so much for numerical code: the same computation on the same array can run 10× faster if the inner loop iterates along the memory-contiguous axis.

Language interoperability is another source of pain. C, C++, Java, C#, Python (NumPy default), and Go are row-major. Fortran, MATLAB, Julia, and R are column-major. When you pass a 2D array between them — say, from Python to a Fortran LAPACK routine — you often have to explicitly transpose the array, or reverse the arguments to the formula, otherwise the two sides will interpret the flat buffer differently and produce silently wrong results. This is one of the classic bug sources in scientific computing.

Finally, the formula generalizes to higher dimensions trivially: for a 3D array with dimensions (D0, D1, D2), the flat index is i = x0 · D1 · D2 + x1 · D2 + x2. Each successive dimension's stride is the product of all following dimensions' sizes. Row-major indexing is really the application of a sequence of multiplications by decreasing strides — an idea that appears in every array library, GPU memory kernel, and tensor framework.

Worked Examples

Given: r = 2, c = 3, C = 4 — solve for flat index i
i = r · C + c = 2 · 4 + 3 = 11
Given: i = 11, C = 4 — solve for row and column
r = ⌊11 / 4⌋ = 2
c = 11 mod 4 = 3
So (r, c) = (2, 3)
Given: (r, c) = (5, 7) in a 10-column array — flat index
i = 5 · 10 + 7 = 57
Given: (r, c) = (0, 0) and 8-byte double elements
i = 0 · C + 0 = 0
Byte offset = 0 · 8 = 0 bytes
Given: (r, c) = (1, 2) in a 3-row column-major array
indexcol-major = c · R + r = 2 · 3 + 1 = 7

Frequently Asked Questions

Because in row-major order you stride over an entire row's worth of elements to get from one row to the next. A row contains num_cols elements, so moving down one row shifts the flat index by num_cols. If you used num_rows, you would be describing column-major order instead — where moving down a column shifts the index by the number of rows. The two are mirror images, and the formula tells you which layout you are working in.

Row-major is used by C, C++, Java, C#, Python (including NumPy by default), Rust, Go, Swift, Kotlin, JavaScript (for typed arrays), and most modern general-purpose languages. Column-major is used by Fortran, MATLAB, Julia, R, and the BLAS/LAPACK linear algebra libraries. Some languages — notably NumPy — let you choose the order when creating an array, with the flag order='C' or order='F'. The default in NumPy is row-major, but many scientific Python workflows explicitly use column-major to interface with Fortran libraries.

Yes — the formula generalizes. For a 3D array with dimensions (D0, D1, D2) in row-major order: index = x0 · D1 · D2 + x1 · D2 + x2, where (x0, x1, x2) is the coordinate. Each dimension's stride is the product of the sizes of all following dimensions. For 4D and beyond the pattern continues. The general principle is that dimension k's stride is the product of dimensions k+1 through the last. This is exactly how NumPy, PyTorch, TensorFlow, and every tensor framework compute flat offsets, and it is why they expose the "stride" of each dimension as a first-class concept.

No — the formula assumes all rows have the same number of columns (a rectangular 2D array), which is the standard case in C-style arrays and NumPy's default. For "jagged" or "ragged" arrays (each row has a different length), you cannot compute a flat index from (r, c) alone; you need the row offsets explicitly. Jagged arrays are typically represented as arrays of arrays, each with its own length, rather than as a single flat buffer with a stride. This is why they are slower to traverse than flat 2D arrays.

The byte offset is the flat index multiplied by the size of each element in bytes. For an int32 array, the element size is 4 bytes; for a double it is 8. The byte offset tells you exactly where in the raw memory buffer the element lives. This matters when you are working with memory-mapped files (mmap), GPU kernels, DMA transfers, or FFI boundaries — anywhere you interact with raw memory rather than a language's native array abstraction. The formula is: byte_offset = i · sizeof(element). Our calculator shows this in the companion metrics.

Yes — the inverse formula is exact and uses only integer arithmetic: row = ⌊index / C⌋ and column = index mod C, where C is the number of columns. Integer division and modulo are exact for any non-negative index and any positive C, so no precision is lost. Our calculator uses this in the "index → row, column" direction. The only subtlety is that if index is out of range (≥ R · C), the formula still returns numbers, but they describe a row that does not exist in the array — the calculator flags this with the validity badge.

It depends entirely on the layout. For a row-major array, iterating along rows (outer loop over rows, inner loop over columns) is fast because consecutive inner iterations touch consecutive memory addresses — the CPU cache line is fully utilized, and the hardware prefetcher can stream the data. Iterating along columns on the same array does a cache miss on nearly every access. The speed difference can easily be 5–10×. The rule of thumb: on a row-major array, keep the last varying index as the innermost loop; on a column-major array, do the opposite. This single change is one of the highest-leverage optimizations in numerical code.

That variant appears when the array is 1-indexed rather than 0-indexed. In 1-based indexing (used by Fortran, MATLAB, and most mathematical notation), the first row is row 1, the first column is column 1, and the first element is index 1. Converting to 0-based gives index0 = (row − 1) · num_cols + (col − 1) = row · num_cols + col − num_cols − 1, which is messier. This calculator uses 0-based indexing throughout, matching C, Java, Python, and every modern general-purpose language. If you are translating a formula from a textbook or a Fortran source, double-check the base before using it.

Calculating...

Variables

Symbol Quantity Unit
index Flat memory index
row Row index (0-based)
num_columns Total number of columns
column Column index (0-based)

What it means

In row‑major order, the elements of a multi‑dimensional array are stored in contiguous memory row by row. For a 2D array with dimensions rows × columns, the 1D index of element (i, j) (0‑based) is computed as i * num_columns + j. This layout is used in languages like C, C++, and Python (with lists of lists often not contiguous, but conceptually row‑major is common). Conversely, column‑major order (used in Fortran and MATLAB) computes index as j * num_rows + i. Row‑major allows efficient sequential access along rows, which improves cache locality for many algorithms. The formula is fundamental for accessing array elements in low‑level programming, optimizing loops, and understanding memory usage. It also applies to higher dimensions: for 3D, index = ((i * depth) + j) * width + k. Knowing the memory layout is crucial for performance, especially in scientific computing, graphics, and machine learning where large multi‑dimensional data is processed. The concept is also used in image processing (e.g., pixel data) and in designing data structures that mimic arrays.

Worked example

2D Array Index – Two Examples

Real‑World
Scenario 1 – Image Buffer: An image has width 800 pixels. What is the index of the pixel at row 300, column 500 (0‑based)?
ParameterValue
row300
col500
num_columns800
1index = row × num_columns + col = 300×800 + 500 = 240,000 + 500 = 240,500
Result Index = 240,500 ✓ Pixel location in buffer
Scenario 2 – Spreadsheet Cell: A spreadsheet has 256 columns. Find the index of cell (42, 127) in memory.
ParameterValue
row42
col127
num_columns256
1index = 42×256 + 127 = 10,752 + 127 = 10,879
Result Index = 10,879 ✓ Memory location
Key insight: Row‑major order stores entire rows consecutively – widely used in C/C++ and image processing.

Common mistakes

  • Column count: The number of columns must be known and constant for all rows.
  • Zero‑based indices: The formula assumes row and column are zero‑based (starting at 0). If using 1‑based, adjust accordingly.
  • Row‑major vs. column‑major: Row‑major is common in C, but column‑major is used in Fortran; verify the memory layout.
  • Bounds checking: Ensure row < num_rows and column < num_columns to avoid out‑of‑bounds access.
  • Stride: If the array has padding or non‑contiguous storage, the simple formula may not hold.

Applications

Row‑major order indexing for a 2D array maps a (row, column) pair to a single index using the formula `index = row * num_columns + column`. This is the standard memory layout for multi‑dimensional arrays in C and C++, as well as for many other languages when using contiguous storage. Understanding this mapping is essential for efficient access, loop optimisation, and when interfacing with low‑level memory (e.g., image processing, matrix multiplication). Engineers use this formula to flatten multi‑dimensional data for storage, to optimise cache locality, and to implement algorithms that operate on matrices and images. It is also critical for understanding how compilers and hardware handle arrays, directly impacting performance.

  • Memory layout of multi‑dimensional arrays
  • Optimisation of nested loops for cache performance
  • Image processing and pixel access
  • Linear algebra and matrix operations
  • Data serialisation and storage