A structured lesson workspace with readable content, hands-on examples, and a clean path to completion.
When you pass an array to a function, it decays to a pointer to its first element. The function does not receive the array. It receives an address. The size information is gone. sizeof inside the function gives you the pointer size (8 bytes on 64-bit), not the array size. This is the single most confusing aspect of C arrays for beginners, and it is the reason every C function that takes an array also takes a length parameter.
#include <stdio.h>void show_sizes(int arr[]) {printf("Inside function:\n");printf(" sizeof(arr) = %zu\n", sizeof(arr));printf(" sizeof(arr[0]) = %zu\n", sizeof(arr[0]));}int main(void) {int data[10] = {0};printf("In main:\n");printf(" sizeof(data) = %zu\n", sizeof(data));printf(" sizeof(data[0]) = %zu\n", sizeof(data[0]));show_sizes(data);return 0;}
In main, sizeof(data) is 40 (10 ints × 4 bytes). Inside the function, sizeof(arr) is 8 (one pointer). The array did not get copied. The function received the address of data[0]. The notation int arr[] in the parameter list is syntactic sugar for int *arr. They are identical. The compiler treats them the same.
#include <stdio.h>double average(const int *arr, int len) {if (len <= 0) return 0.0;long sum = 0;for (int i = 0; i < len; i++) {sum += arr[i];}return (double)sum / len;}void print_array(const int *arr, int len) {printf("[");for (int i = 0; i < len; i++) {printf("%d", arr[i]);if (i < len - 1) printf(", ");}printf("]\n");}int main(void) {int scores[] = {85, 92, 78, 96, 88};int n = sizeof(scores) / sizeof(scores[0]);print_array(scores, n);printf("Average: %.1f\n", average(scores, n));return 0;}
The sizeof trick works in main because data is still an array there. It does not work inside average because arr is a pointer. The length must be computed at the call site and passed explicitly. This is not a limitation to work around. It is the C memory model. Arrays are not objects with metadata. They are raw memory with a convention.
Since the function receives a pointer to the original memory, writing to arr[i] modifies the caller's data. No copy was made. This is efficient for large arrays but means you must use const if the function should be read-only.
#include <stdio.h>void double_values(int *arr, int len) {for (int i = 0; i < len; i++) {arr[i] *= 2;}}int main(void) {int data[] = {1, 2, 3, 4, 5};int n = 5;printf("Before: ");for (int i = 0; i < n; i++) printf("%d ", data[i]);printf("\n");double_values(data, n);printf("After: ");for (int i = 0; i < n; i++) printf("%d ", data[i]);printf("\n");return 0;}
Every C standard library function that operates on arrays takes a length or a sentinel. memcpy takes a byte count. strlen walks to a null terminator. qsort takes an element count. The pattern is universal because the language gives you no alternative. Next: dynamic memory allocation, where we leave the stack behind and manage heap memory manually.
Finish the lesson once you have worked through the material. This awards ★ 30 XP.