Skip to main content

Data Structures

Arrays

Master 1D & 2D Arrays — what/why/applications, types, initialization, reading and writing data — using LEARNCODEGURU’s 6-level learning model.

Level 1 Basics Content

C Arrays Overview

An array stores many values of the same type in one named block of contiguous memory. You access each value with an index (starting at 0). This level covers 1D and 2D arrays: what they are, why they matter, types, declaration, initialization, writing data in, reading data out, and one sample program.

Think of a 1D array as a single row of boxes, and a 2D array as a matrix (rows × columns). Both use the same ideas: fixed size at declaration (for classic arrays), zero-based indexing, and loops for fill / print.

Topic 1

Overview — storing many values together

Without arrays you would need many separate variables (m1, m2, …). Arrays give you one name and an index: marks[0], marks[1], …

  • Element — one value in the array
  • Index — position; first element is index 0
  • Size / length — how many elements (1D) or rows×cols (2D)
  • Same type — all elements share one type (int, float, …)
An array in C stored as contiguous memory: one name with elements accessed by index starting at 0, each element of the same data type, shown for a 1D array and as rows and columns for a 2D array.
An array stores many values of one type under a single name, accessed by index
Declare → initialize or write → read / process with loops → print results
Topic 2

What is an array? — 1D then 2D

A 1D array is a contiguous sequence of elements. Address of element i is conceptually base address + i × sizeof(element).


int a[5];   /* 5 ints: a[0] a[1] a[2] a[3] a[4] */

A 2D array is like a table: first index = row, second = column. m[i][j] is the element in row i, column j.


int m[2][3];   /* 2 rows, 3 columns — 6 ints total */
/* m[0][0] m[0][1] m[0][2] */
/* m[1][0] m[1][1] m[1][2] */
Remember: indices start at 0. For a[n], last valid index is n - 1. For m[r][c], last row is r - 1, last col is c - 1.
Topic 3

Why arrays?

  • Store many values under one name instead of dozens of variables
  • Random access — jump to any index in constant time with a[i]
  • Easy looping — for from 0 to n - 1 for fill, sum, search, print
  • Natural for tables — 2D arrays model matrices, grids, and game boards
  • Less clutter — algorithms stay readable when data lives in arrays
Topic 4

Applications of arrays

  • Marks / scores list — 1D array of student marks
  • Matrices — addition, multiplication (conceptually), transpose with 2D arrays
  • Images (conceptually) — pixels as a 2D grid of values
  • Lookup tables — precomputed values indexed by an integer key
  • Strings (related) — char arrays hold text ending with '\0'
Topic 5

Types of arrays

Type Idea Example declaration Access
1D (one-dimensional) Single list / vector int a[10]; a[i]
2D (two-dimensional) Matrix / table (rows × cols) int m[3][4]; m[i][j]
Multi-dimensional 3D+ (cube, layers) — rare in intro courses int t[2][3][4]; t[i][j][k]
Array of char / string Characters in a row; C string if null-terminated char s[20]; s[i] or %s
Focus first on 1D and 2D. Multi-D is the same idea with more indices. Strings are “arrays of char” plus the special '\0' terminator — covered deeply in a strings lesson.
Topic 6

Declaration syntax — 1D and 2D

1D:


type name[size];

int marks[5];
float temp[7];
char vowels[5];

2D:


type name[rows][cols];

int matrix[3][3];   /* 3×3 ints */
int grid[2][4];     /* 2 rows, 4 columns */
Size: for classic fixed arrays, the size in brackets must be a constant expression known at compile time (unless you use a C99 VLA in a local scope).
Topic 7

Initialization of arrays — 1D and 2D

Compile-time (initializer list) — 1D:


int a[5] = {10, 20, 30, 40, 50};
int b[]  = {1, 2, 3};           /* size becomes 3 */
int c[5] = {1, 2};            /* partial: rest become 0 */
int z[5] = {0};              /* all zeros */
1D form Meaning
int a[3] = {1, 2, 3}; Full init — every element set
int a[5] = {1, 2}; Partial — a[2]..a[4] are 0
int a[] = {1, 2, 3}; Size inferred as 3
int a[5]; (no init) Automatic storage → indeterminate until you write

Compile-time — 2D:


int m[2][3] = {
    {1, 2, 3},
    {4, 5, 6}
};

int p[2][3] = {1, 2};   /* partial: rest 0 */
int q[2][3] = {0};     /* all zeros */
2D form Meaning
Nested braces per row Clearest — each inner list is one row
Flat list {1,2,3,4,5,6} Filled in row-major order
Partial init Unspecified elements become 0
Topic 8

Writing data into arrays — 1D and 2D

Assignment (1D):


a[0] = 10;
a[1] = 20;
a[2] = 30;

Loop + scanf (1D):


for (i = 0; i < n; i++)
    scanf("%d", &a[i]);

Assignment (2D):


m[0][0] = 1;
m[0][1] = 2;
m[1][0] = 3;

Nested loop + scanf (2D):


for (i = 0; i < rows; i++)
    for (j = 0; j < cols; j++)
        scanf("%d", &m[i][j]);
Always pass the address of the element to scanf: &a[i] or &m[i][j].
Topic 9

Reading data from arrays — 1D and 2D

Loop + printf (1D):


for (i = 0; i < n; i++)
    printf("%d ", a[i]);
printf("\n");

Nested loops + printf (2D matrix form):


for (i = 0; i < rows; i++) {
    for (j = 0; j < cols; j++)
        printf("%d ", m[i][j]);
    printf("\n");          /* new line after each row */
}
Pattern: outer loop = rows, inner loop = columns. Print a newline after each row so the output looks like a matrix.
Example

Sample program — 1D input/print + small 2D print

Reads n integers into a 1D array and prints them. Then shows a tiny hardcoded 2×3 matrix printed with nested loops:


/* Arrays — 1D read/print + small 2D print sample */
#include <stdio.h>

int main(void) {
    int n, i, j;
    int a[100];
    int m[2][3] = {
        {1, 2, 3},
        {4, 5, 6}
    };

    printf("Enter n (1..100): ");
    scanf("%d", &n);

    printf("Enter %d integers:\n", n);
    for (i = 0; i < n; i++)
        scanf("%d", &a[i]);

    printf("1D array: ");
    for (i = 0; i < n; i++)
        printf("%d ", a[i]);
    printf("\n");

    printf("2D matrix:\n");
    for (i = 0; i < 2; i++) {
        for (j = 0; j < 3; j++)
            printf("%d ", m[i][j]);
        printf("\n");
    }

    return 0;
}
What to observe: 1D uses one loop with &a[i] / a[i]; 2D uses nested loops and a newline per row. Keep n within the declared capacity (here 100).

Level 2 Advanced Content

Going deeper into arrays

Level 1 covered declare / init / read / write. Level 2 explains memory layout, bounds safety, array-to-pointer decay, sizeof for length, passing arrays to functions, 2D as an array of rows, and common mistakes.

Topic 1

Memory layout — 1D and row-major 2D

A 1D array occupies consecutive addresses. For int a[4], elements sit next to each other in order a[0], a[1], a[2], a[3].

A 2D array in C is stored in row-major order: all of row 0, then row 1, and so on. For int m[2][3] the sequence in memory is:

m[0][0] → m[0][1] → m[0][2] → m[1][0] → m[1][1] → m[1][2]
That is why the compiler needs the column count when computing the address of m[i][j]: skip i full rows of cols elements, then add j.
Topic 2

Index out of bounds — undefined behavior

C does not automatically stop you from writing a[n] or m[i][j] outside the declared ranges. Doing so is undefined behavior: the program may crash, corrupt data, or seem fine until later.

  • 1D: use only 0 .. size-1
  • 2D: use only 0 .. rows-1 and 0 .. cols-1
  • Prefer i < n over i <= n for 0-based loops
Topic 3

Array name decays to a pointer (high-level)

In most expressions, the array name a decays to a pointer to its first element (&a[0]). That is why you can pass a to a function that expects int *, and why a[i] relates to *(a + i).

Important exception: sizeof(a) still sees the whole array object (in the declaring scope), not a pointer — until the name has decayed in a parameter.

Topic 4

Length with sizeof(array) / sizeof(array[0])


int a[] = {10, 20, 30, 40};
int n = sizeof(a) / sizeof(a[0]);  /* n == 4 */
Context What sizeof(a) means Safe length trick?
Same scope as declaration Total bytes of the array Yes — divide by element size
Function parameter int a[] Size of a pointer No — pass n explicitly
2D int m[2][3] Bytes for all 6 ints Rows = sizeof(m)/sizeof(m[0]); cols = sizeof(m[0])/sizeof(m[0][0])
Topic 5

Passing arrays to functions — intro

Functions receive a pointer to the first element (decay), not a copy of the whole array. Changes inside the function affect the caller’s array. Always pass the length for 1D.


void print1d(int a[], int n) {
    int i;
    for (i = 0; i < n; i++)
        printf("%d ", a[i]);
}

/* 2D: column size must be known (or use other pointer forms) */
void print2d(int m[][3], int rows) {
    int i, j;
    for (i = 0; i < rows; i++) {
        for (j = 0; j < 3; j++)
            printf("%d ", m[i][j]);
        printf("\n");
    }
}
Topic 6

2D as array of arrays — nested traversal

You can think of int m[rows][cols] as rows arrays of length cols. m[i] is row i; m[i][j] is one cell.


/* Row-major walk — visit every cell once */
for (row = 0; row < rows; row++)
    for (col = 0; col < cols; col++)
        /* use m[row][col] */ ;
  • By rows: outer = row, inner = col (most common)
  • By columns: outer = col, inner = row (still valid; different visit order)
  • Always print \n after finishing one row when showing a matrix
Topic 7

Common mistakes

Mistake Why it hurts Fix
Off-by-one (i <= n) Touches a[n] — out of bounds Use i < n for 0-based arrays
Wrong 2D dimensions Loops use different rows/cols than declaration Match declared sizes; name rows/cols
Reading uninitialized elements Garbage output / UB if used Init with list, zeros, or write before read
sizeof inside a function on parameter Gets pointer size, not length Pass n (and cols for 2D)
Forgetting & in scanf Wrong address / crash scanf("%d", &a[i])

Level 3 C Tricky Interview Points

Advanced tricky interview points on 1D / 2D arrays, indexing, sizeof, decay, bounds, initialization zeros, and row-major layout.

Tricky Interview Point-1:

Array index starts at 0 — last index is size − 1

For int a[5], valid indices are 0..4. Accessing a[5] is out of bounds. Interviewers often ask “what is the last element?” — answer a[4], not a[5]. Same rule for each dimension of a 2D array.

Tricky Interview Point-2:

Out-of-bounds access is undefined behavior — may not always crash

C does not check array bounds at runtime. a[n] or a[-1] can overwrite other memory, appear to “work,” or crash later. Never rely on “it printed something” as proof that an index is valid.

Tricky Interview Point-3:

sizeof(arr) / sizeof(arr[0]) gives element count only for real arrays

Inside the same scope where the array is declared, sizeof(a)/sizeof(a[0]) is the length. After the array decays to a pointer (e.g. in a function parameter), sizeof(a) is the pointer size — not the array length. Pass n separately.

Tricky Interview Point-4:

Array name decays to &arr[0] in most expressions

Except for sizeof, & (address-of the whole array), and a few other contexts, arr means &arr[0] — a pointer to the first element. That is why you pass arr to a function without & for 1D arrays of ints.

Tricky Interview Point-5:

int a[5] = {1, 2}; remaining elements become 0

Partial initialization zeros the rest of the array (for static/automatic with initializer list). int a[5] = {0}; zeros all five. Uninitialized automatic arrays hold indeterminate (garbage) values — a common exam trap.

Tricky Interview Point-6:

2D arrays are stored in row-major order in C

For int m[2][3], memory is row0 then row1: m[0][0], m[0][1], m[0][2], m[1][0], …. Address of m[i][j] advances by j within a row, then by whole rows. Column-major is Fortran’s style, not C’s.

Tricky Interview Point-7:

When passing 2D arrays, all dimensions except the first must be known

void f(int a[][3], int rows) is valid; void f(int a[][], int r, int c) is not (without VLAs / pointers). The compiler needs the column size to compute row offsets in row-major layout.

Tricky Interview Point-8:

char s[] = "Hi"; has size 3 — includes the null terminator

String literals end with '\0'. sizeof(s) is 3 (H, i, \0). Length from strlen is 2. Arrays of char are closely related to C strings; confusing sizeof and strlen is a classic interview point.

Tricky Interview Point-9:

a[i] is identical to *(a + i) — and i[a] also works

Subscripting is defined via pointer arithmetic. a[i] ≡ *(a + i). Because addition is commutative, i[a] also compiles — a trick question, not a style to use. Same idea extends to 2D via nested offsets.

Tricky Interview Point-10:

Missing row size in int a[][COLS] vs wrong COLS breaks indexing

If you declare or pass with COLS = 3 but treat columns as 4 in nested loops, you silently read/write the wrong elements. Always match declared columns with loop bounds.

Tricky Interview Point-11:

VLA (C99): int a[n]; size from runtime — not allowed as a global

Variable-length arrays need a local (block) scope and a positive size. They cannot be initialized with = {…} in older rules the same way as fixed arrays. Many interviewers ask whether VLAs are ISO C++ — they are not standard C++.

Tricky Interview Point-12:

Nested loops for 2D: outer = rows, inner = columns

for (i = 0; i < rows; i++) for (j = 0; j < cols; j++) visits a[i][j] in row-major order. Swapping bounds or using <= instead of < causes off-by-one or out-of-bounds bugs — same traps as pattern printing.

Interview tip: Always state valid index ranges, whether the array was initialized, and whether sizeof is applied to a real array or a decayed pointer parameter.

Level 4 Simple Programs

Short programs demonstrating 1D I/O with sum/max, 2D matrix I/O, and 2D init + matrix print.

Program 1 — 1D array input/output + sum/max


/* 1D: read n ints, print them, sum, and maximum */
#include <stdio.h>

int main(void) {
    int n, i, sum = 0, max;
    int a[100];

    printf("Enter n: ");
    scanf("%d", &n);

    printf("Enter %d integers:\n", n);
    for (i = 0; i < n; i++)
        scanf("%d", &a[i]);

    max = a[0];
    printf("Array: ");
    for (i = 0; i < n; i++) {
        printf("%d ", a[i]);
        sum += a[i];
        if (a[i] > max)
            max = a[i];
    }
    printf("\nSum = %d\nMax = %d\n", sum, max);

    return 0;
}

Program 2 — 2D matrix input/output


/* 2D: read rows×cols matrix and print it */
#include <stdio.h>

int main(void) {
    int rows, cols, i, j;
    int m[20][20];

    printf("Enter rows and cols: ");
    scanf("%d %d", &rows, &cols);

    printf("Enter matrix elements:\n");
    for (i = 0; i < rows; i++)
        for (j = 0; j < cols; j++)
            scanf("%d", &m[i][j]);

    printf("Matrix:\n");
    for (i = 0; i < rows; i++) {
        for (j = 0; j < cols; j++)
            printf("%d ", m[i][j]);
        printf("\n");
    }

    return 0;
}

Program 3 — Initialize 2D and print in matrix form


/* 2D: compile-time init, print as matrix */
#include <stdio.h>

int main(void) {
    int i, j;
    int m[3][3] = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    };

    printf("3x3 matrix:\n");
    for (i = 0; i < 3; i++) {
        for (j = 0; j < 3; j++)
            printf("%4d", m[i][j]);
        printf("\n");
    }

    return 0;
}
Comment Directive Type Keyword Function Variable String Number

Level 5 Problem Solving Tricks

How to master arrays while solving problems

Most array bugs come from wrong indices, uninitialized elements, mismatched 2D dimensions, and forgetting that C does not check bounds. Use these colorful habits every time you fill, traverse, or print 1D and 2D arrays.

Trick 1

Trace indices on paper for a tiny size first

Before coding, draw a[0]..a[n-1] or a small 2×3 matrix and label every index. Hand-trace one read loop and one write loop. Most off-by-one bugs die on paper before they reach the compiler.

Trick 2

Decide rows × cols once — then lock loop bounds

Write rows and cols (or R and C) at the top. Outer loop: 0 .. rows-1. Inner: 0 .. cols-1. Never mix 1-based thinking with 0-based arrays without converting carefully.

Trick 3

Validate bounds before every access

Ask: is index >= 0 and < size? For 2D: 0 <= i < rows and 0 <= j < cols. If the problem gives positions from the user, reject invalid indices instead of accessing blindly.

Trick 4

Initialize before you read — zeros or input

Uninitialized automatic arrays are garbage. Either fill with scanf/assignment loops, or use = {0} / explicit zeros when “empty” means zero. Never print an array you have not written into.

Trick 5

Draw the matrix when doing 2D tasks

For transpose, diagonal, or neighbor problems, sketch the grid and mark the cells you touch. Code follows the drawing: row i, column j — not the other way around unless the problem says so.

Trick 6

Use sizeof only on the real array object

Compute n = sizeof(a)/sizeof(a[0]) in the declaring scope. In functions, take an explicit length parameter. For 2D, track rows and cols yourself; do not assume sizeof “knows” both dimensions after decay.

Trick 7

Name counters i/j or row/col — never reuse one index for both

int i for 1D is fine. For 2D prefer row and col (or i and j consistently). Reusing one variable for outer and inner loops corrupts the outer counter and scrambles the matrix walk.

Trick 8

Match scanf/printf format to the element type

int → %d with &a[i] or &m[i][j]. float → %f. char arrays/strings → %s without & on the array name. One mismatched specifier and the whole array fill looks “random.”

Quick success checklist

  • Before run: size declared? indices 0..n-1? written before read? scanf has &?
  • Debug order: trace tiny n / 2×3 on paper → check loop bounds → verify row newlines
  • 2D habit: draw the matrix → lock rows/cols → outer=row, inner=col → validate every i,j
Level-5 goal: treat every array access as “index must be legal,” keep 1D and 2D loop patterns muscle-memory, and never trust output from uninitialized cells.

Level 6 Practice Programs List

Programming questions only — focused on 1D and 2D arrays: init, read, write, traverse, and simple matrix tasks.

  1. 1. Write a C program that reads n integers into a 1D array, then prints them in order and in reverse.
  2. 2. Write a C program that reads n integers into a 1D array and prints their sum and average.
  3. 3. Write a C program that finds the maximum and minimum values in a 1D array of n integers.
  4. 4. Write a C program that initializes a 1D array at compile time and prints each element with its index.
  5. 5. Write a C program that reads a 2D matrix of size r×c, then prints it in matrix (row) form.
  6. 6. Write a C program that reads two 2×2 matrices, adds them element-wise, and prints the result matrix.
  7. 7. Write a C program that prints the main diagonal elements of an n×n matrix (read n and the matrix).
  8. 8. Write a C program that counts how many even numbers appear in a 2D integer matrix.