An array is a fixed-size, contiguous block of memory holding elements of the same type, indexed starting at zero.
int scores[5] = {90, 85, 77, 92, 60}; // fixed size, known at declaration
scores[0] = 95; // modify an element by index
int grid[2][3] = {{1, 2, 3}, {4, 5, 6}}; // 2D array: 2 rows, 3 columns
printf("%d\n", scores[2]); // 77
printf("%zu\n", sizeof(scores) / sizeof(scores[0])); // 5 — element count trick
An array's size is fixed once declared — C arrays cannot grow or shrink at runtime, unlike arrays in many higher-level languages; a fixed-size array that needs to grow must be manually reallocated (covered in the Dynamic Memory chapter) or replaced with a larger one.
C performs no automatic bounds checking: reading or writing scores[10] on a 5-element array doesn't raise an error, it silently reads or corrupts whatever memory happens to sit past the array — a common source of serious bugs, so the programmer is fully responsible for staying within bounds.
A critical gotcha: sizeof(scores) gives the array's total byte size only while the array itself is directly in scope; the moment an array is passed to a function, it decays into a plain pointer to its first element, and sizeof inside that function would report the pointer's size (commonly 8 bytes), not the array's — which is why functions that receive arrays must also receive their length as a separate parameter.