When learning C programming, working with arrays is usually straightforward until you encounter multidimensional arrays and memory management expressions like sizeof(fruits) / sizeof(fruits[0]). If you've wondered why division is necessary to determine an array's length, you are not alone.

The Fundamental Concept: How Arrays Exist in Memory

In C, a 2D array is fundamentally an array of arrays. Under the hood, memory is linear (1D). When you declare a 2D array like char fruits[3][10], C allocates a single contiguous block of memory large enough to hold all elements sequentially.

Consider the structure from the code example:

char fruits[][10] = {
    {'A', 'p', 'p', 'l', 'e', '\0', '\0', '\0', '\0', '\0'},
    {'B', 'a', 'n', 'a', 'n', 'a', '\0', '\0', '\0', '\0'},
    {'C', 'o', 'c', 'o', 'n', 'u', 't', '\0', '\0', '\0'}
};

This array has 3 rows, where each row is an array of 10 char elements. Because a char occupies 1 byte of memory in C, each row takes up 10 bytes.

Breaking Down the sizeof() Expressions

The sizeof operator returns the total memory size in bytes occupied by an object or type, not the count of elements. Let's break down each term used in the calculation:

  • sizeof(fruits): This evaluates the total memory occupied by the entire 2D array. Since there are 3 rows and each row contains 10 characters (10 bytes), this returns 3 * 10 * 1 byte = 30 bytes.
  • sizeof(fruits[0]): fruits[0] represents the first row of the array (a 1D array of 10 characters). The size of this single row is 10 * 1 byte = 10 bytes.
  • sizeof(fruits[0][0]): This represents a single element in the array (the first character of the first row). A single char equals 1 byte.

Why Do We Divide?

Because sizeof reports total bytes rather than count, you must use basic math to find the dimensions of the array:

1. Finding the Number of Rows (Array Outer Length)

To find out how many items (rows) are in the outer array, you divide the total byte size of the entire 2D array by the byte size of a single row:

int num_rows = sizeof(fruits) / sizeof(fruits[0]);
// Calculation: 30 bytes / 10 bytes = 3 rows

2. Finding the Number of Columns (Row Capacity)

To find out how many elements are in each individual row (columns), you divide the byte size of one row by the byte size of a single element within that row:

int num_cols = sizeof(fruits[0]) / sizeof(fruits[0][0]);
// Calculation: 10 bytes / 1 byte = 10 columns

3. Finding Total Elements Across All Rows

If you want the total count of individual characters allocated across the entire array:

int total_elements = sizeof(fruits) / sizeof(fruits[0][0]);
// Calculation: 30 bytes / 1 byte = 30 elements

A Critical Pitfall: Array Decay in Functions

While the sizeof(arr) / sizeof(arr[0]) idiom works perfectly in the scope where the array is declared, it fails when passed into functions. When you pass an array to a function in C, it automatically decays into a pointer to its first element.

void printFruits(char arr[][10]) {
    // DANGER: sizeof(arr) now returns the size of a pointer (usually 4 or 8 bytes),
    // NOT the size of the full array!
    int size = sizeof(arr) / sizeof(arr[0]); // Incorrect result!
}

To handle arrays cleanly inside functions, always calculate the array length using the sizeof division trick in the original scope and pass the size parameter explicitly into your function.

Summary

The division inside sizeof(fruits) / sizeof(fruits[0]) is simply converting unit sizes from total bytes allocated into number of sub-arrays (rows). Understanding this memory model is key to mastering C array manipulation and pointer arithmetic.