C Programming 3 min read

Arrays and strings

A C array is a fixed block of elements with no bounds checking. Passed to a function, it decays to a pointer to its first element, so its length must travel separately. A string is a char array ending in a zero byte: strlen counts the characters before it, sizeof the whole array.

Left, in main: readings is an array of four int values, 16 bytes with a 4-byte int, so sizeof gives its full size and the count can be computed. Right, inside sum: the parameter values is only a pointer to the first element, so sizeof gives the pointer's size and the count n has to be passed in.
In main the array knows its size; in sum() it is only a pointer, so n is passed too.

Fixed size, no checks

int readings[4] reserves room for exactly four int values, side by side. The size is fixed when the program is built, and C never checks an index: readings[4] reads or writes whatever lies beyond the array. In the function where the array is defined, sizeof readings / sizeof readings[0] gives its element count.

Arrays decay to pointers

Pass an array to a function and the function receives a pointer to its first element. A parameter written int values[] is really int *values, and sizeof inside the function gives the size of a pointer, not of the array. So functions take the length as a separate argument, as sum() does below.

arrays.cC
#include <stdio.h>#include <string.h>#define COUNT(a) (sizeof(a) / sizeof((a)[0]))static int sum(const int *values, size_t n) {   /* the array arrives as a pointer */    int total = 0;    for (size_t i = 0; i < n; i++) {        total += values[i];    }    return total;}int main(void) {    int readings[] = {3, 5, 7, 9};    char name[8] = "UART1";    char buf[8];    printf("elements: %zu, sum: %d\n", COUNT(readings), sum(readings, COUNT(readings)));    printf("strlen: %zu, sizeof: %zu\n", strlen(name), sizeof name);    int needed = snprintf(buf, sizeof buf, "%s-%d", name, 115200);    printf("buf: \"%s\" (needed %d chars)\n", buf, needed);    return 0;}
Output
elements: 4, sum: 24
strlen: 5, sizeof: 8
buf: "UART1-1" (needed 12 chars)

Strings and the terminating zero

A C string is a char array whose text ends with a zero byte, '\0'. name[8] = "UART1" holds five characters, the zero, and two unused bytes: strlen gives 5, sizeof gives 8. Every string function relies on that zero; without it they read on past the end. snprintf never writes more than the size it is given, always ends the text with a zero, and returns the length it needed, so truncation can be detected.