A structured lesson workspace with readable content, hands-on examples, and a clean path to completion.
sizeof(arr) / sizeof(arr[0]) computes the number of elements in an array. It works because sizeof(arr) gives the total byte size of the array and sizeof(arr[0]) gives the byte size of one element. The division yields the count. But this only works in the scope where arr was declared as an array. Pass arr to a function and it decays to a pointer. sizeof gives the pointer size. The element count is lost. This is the most repeated mistake in C array code.
#include <stdio.h>void wrong_length(int arr[]) {printf("Inside function: sizeof(arr)=%zu, elements=%zu\n",sizeof(arr), sizeof(arr) / sizeof(arr[0]));}int main(void) {int data[] = {10, 20, 30, 40, 50, 60, 70};int n = sizeof(data) / sizeof(data[0]);printf("In main: sizeof(data)=%zu, elements=%d\n",sizeof(data), n);wrong_length(data);return 0;}
In main, sizeof(data) is 28 (7 ints × 4 bytes). The count is 7. Inside the function, sizeof(arr) is 8 (one pointer on a 64-bit system). The count is 8/4 = 2, which is wrong. The array decayed to a pointer at the function boundary. The size information is gone. The only way to know the length inside the function is to pass it as a separate parameter.
#include <stdio.h>#define ARRAY_LEN(arr) (sizeof(arr) / sizeof((arr)[0]))int main(void) {int nums[] = {1, 2, 3, 4, 5};double vals[] = {1.1, 2.2, 3.3};char chars[] = "hello";printf("nums: %zu elements\n", ARRAY_LEN(nums));printf("vals: %zu elements\n", ARRAY_LEN(vals));printf("chars: %zu bytes (includes null)\n", ARRAY_LEN(chars));return 0;}
The macro works for any array type. The parentheses around (arr)[0] prevent operator precedence issues if the argument is an expression. The macro only works in the declaring scope. If you pass the array to a function, the macro silently gives the wrong answer. Some codebases add a compile-time check using _Static_assert to detect decay, but the simplest defense is discipline: compute the length at the call site and pass it.
The sizeof trick is convenient and correct in one place: the scope where the array was declared. Everywhere else, pass the length. This is not a limitation to resent. It is the C memory model. Arrays are raw memory. You track the size. Next: if statement best practices, including the Yoda condition debate and brace discipline.
Finish the lesson once you have worked through the material. This awards ★ 20 XP.