Arrays
An array stores a fixed number of values of the same type side by side in memory. Arrays are C's most basic collection — fast and simple, but with one big catch: C never checks that an index is inside the array.
Declaring and using
#include <stdio.h> int main(void) { int scores[5] = { 72, 85, 90, 64, 88 }; printf("First: %d, last: %d\n", scores[0], scores[4]); scores[3] = 70; // change an element int total = 0; for (int i = 0; i < 5; i++) { total += scores[i]; } printf("Average: %.1f\n", total / 5.0); return 0; }
First: 72, last: 88 Average: 81.0
Indexes start at 0, so a 5-element array has indexes 0 to 4. The size must be fixed when the array is created.
Initialisation
#include <stdio.h> int main(void) { int a[5] = { 1, 2 }; // the rest are 0 int b[5] = { 0 }; // all zero int c[] = { 3, 6, 9 }; // size taken from the list: 3 int d[6] = { [2] = 50, [5] = 80 }; // designated initialisers (C99) for (int i = 0; i < 5; i++) printf("%d ", a[i]); printf("| "); for (int i = 0; i < 5; i++) printf("%d ", b[i]); printf("| %zu elements in c | ", sizeof c / sizeof c[0]); for (int i = 0; i < 6; i++) printf("%d ", d[i]); printf("\n"); return 0; }
1 2 0 0 0 | 0 0 0 0 0 | 3 elements in c | 0 0 50 0 0 80
Once any element is initialised, all the others are set to zero. A local array with no initialiser at all contains garbage, like any uninitialised variable.
The element count
sizeof on an array gives its total size in bytes; divide by one element's size to get the count. A macro makes this convenient:
#include <stdio.h> #define COUNT_OF(arr) (sizeof (arr) / sizeof (arr)[0]) int main(void) { const char *planets[] = { "Mercury", "Venus", "Earth", "Mars" }; for (size_t i = 0; i < COUNT_OF(planets); i++) { printf("%zu: %s\n", i + 1, planets[i]); } return 0; }
1: Mercury 2: Venus 3: Earth 4: Mars
This only works where the array itself is visible. Inside a function that received the array as a parameter, sizeof gives the size of a pointer instead (lesson 32) — which is why functions take the length as a separate parameter.
No bounds checking
Reading or writing past the end of an array is undefined behaviour. C won't stop you: the program may read garbage, corrupt other variables, crash, or seem to work and fail later. This is the source of buffer-overflow security holes. Compilers catch the obvious cases:
#include <stdio.h> int main(void) { int data[3] = { 1, 2, 3 }; printf("%d\n", data[3]); return 0; }
main.c:5:20: warning: array index 3 is past the end of the array (that has type 'int[3]') [-Warray-bounds]
But they can't catch an index computed at run time. Always make sure loop limits and indexes come from the array's real length, and validate any index that comes from input. Tools like AddressSanitizer catch these errors while testing (lesson 38).
Arrays can't be assigned
You can't copy an array with = or compare two with ==. Copy element by element, or with memcpy from <string.h>:
#include <stdio.h> #include <string.h> int main(void) { int original[4] = { 5, 10, 15, 20 }; int copy[4]; memcpy(copy, original, sizeof original); copy[0] = 99; printf("original[0] = %d, copy[0] = %d\n", original[0], copy[0]); printf("equal? %s\n", memcmp(original, copy, sizeof original) == 0 ? "yes" : "no"); return 0; }
original[0] = 5, copy[0] = 99 equal? no
Common array algorithms
#include <stdio.h> int main(void) { int values[] = { 4, 17, -3, 8, 17, 2 }; int n = sizeof values / sizeof values[0]; int max = values[0], max_at = 0; for (int i = 1; i < n; i++) { if (values[i] > max) { max = values[i]; max_at = i; } } printf("max %d at index %d\n", max, max_at); for (int i = 0, j = n - 1; i < j; i++, j--) { // reverse in place int tmp = values[i]; values[i] = values[j]; values[j] = tmp; } for (int i = 0; i < n; i++) printf("%d ", values[i]); printf("\n"); return 0; }
max 17 at index 1 2 17 8 -3 17 4
Variable-length arrays
C99 allowed array sizes decided at run time (int buffer[n];), called VLAs. They became optional in C11, MSVC doesn't support them, and a large n can overflow the stack. Prefer a fixed maximum size or malloc (lesson 36) for sizes known only at run time.
Try it yourself
Count how often each die face appears in a list of rolls, using an array of counters indexed by the face value.
1: ## (2) 2: # (1) 3: #### (4) 4: # (1) 5: # (1) 6: ### (3)