Home/Blog/C

// C

Array index out of bounds in C: why there is no error

Every example on this page was run on 12 October 2026 in C17, and the output under each one is what it printed. How we test these posts.

An array index out of bounds in C means the program used a[i] with i below 0, or equal to or past the array’s length. C never checks the index, so there is usually no error at all: the program reads whatever sits next in memory, or overwrites it. The fix is to keep every index below the length, taken from sizeof a / sizeof a[0], and to build with -fsanitize=address,undefined to find the line that does it.

Our C compiler checks every index into a declared array, so the examples on this page stop on the bad line with a short message. gcc and clang without a sanitizer do not, which is why the same programs behave so differently on your own machine.

What happens when you access an array out of bounds in C?

Accessing an array out of bounds in C is undefined behavior: the language promises nothing about what happens next. This program has two numbers and then asks for the sixth:

#include <stdio.h>

int main(void) {
    int scores[2] = {90, 75};
    int i = 5;
    printf("start\n");
    printf("%d\n", scores[i]);
    return 0;
}

Output

start
main.c:7: array index out of bounds

The page stopped on line 7, the line that reads scores[i] with i equal to 5. Built with plain gcc main.c, the same program usually prints a number nobody put there and carries on. It may also crash much later, or seem to work, which is the worst outcome of the three because the bug ships.

Why is there no error or segmentation fault?

C has no error for an out-of-bounds index because the compiler turns scores[i] into plain address arithmetic and never compares i with the length. Checking every access would cost time, and C leaves that choice to you.

A segmentation fault is not a bounds check either. The operating system hands memory to a program in whole pages and only stops it when an address falls outside every page the program owns. An index a little past the end almost always lands on memory that belongs to the program, often another variable on the stack, so nothing complains. Only a wild index, far from the array, reaches memory the program does not own and gets the segfault.

Why does my loop read past the end of the array?

A loop reads past the end of an array in C when its condition counts to the length instead of below it. An array of n items has indexes 0 to n - 1, so i <= n reads one past the end on its last pass:

#include <stdio.h>

int main(void) {
    int scores[3] = {90, 75, 60};
    int total = 0;
    for (int i = 0; i <= 3; i++) {
        total += scores[i];
    }
    printf("%d\n", total);
    return 0;
}

Output

main.c:7: array index out of bounds

Two other habits cause the rest. A length taken from somewhere else drifts: the array changed size and the loop limit did not. An index from input, a file or a calculation was never checked against the array’s size.

What happens when you write past the end of an array?

Writing past the end of an array in C is the dangerous case, because it changes memory that belongs to something else. The same <= mistake in a loop that fills an array writes one element too many:

#include <stdio.h>

int main(void) {
    int counts[3];
    for (int i = 0; i <= 3; i++) {
        counts[i] = 0;
    }
    printf("done\n");
    return 0;
}

Output

main.c:6: array index out of bounds

On your own machine, without a sanitizer, that extra write lands on whatever the compiler placed next to counts. It can zero another variable, which then shows a value your code never gave it. If it is the loop counter i, the loop starts again and never ends. If it is the stack protector’s guard value, which Ubuntu’s gcc turns on by default, the program dies when the function returns, not on the bad line, with:

*** stack smashing detected ***: terminated

That message names no line. Our page names the line instead, and so does a sanitizer build on your machine.

Why does a char array need room for the ‘\0’?

A C string ends at the first '\0', so a char array needs one more element than the visible text. C even lets char name[5] = "Hello"; compile: the five letters fit, the '\0' is silently dropped, and anything that looks for the end of the string walks off the array:

#include <stdio.h>

int main(void) {
    char name[5] = "Hello";
    int len = 0;
    while (name[len] != '\0') {
        len++;
    }
    printf("%d\n", len);
    return 0;
}

Output

main.c:6: array index out of bounds

printf("%s", name), strlen and strcpy do the same walk, and on your machine they print or copy whatever follows the array until they happen to meet a zero byte. Leave the size out and C counts it for you, '\0' included:

#include <stdio.h>
#include <string.h>

int main(void) {
    char name[] = "Hello";
    printf("%zu %zu\n", sizeof name, strlen(name));
    return 0;
}

Output

6 5

How do I check an array index in C?

Check an array index in C by comparing it with the length yourself, and take the length from the array so the two cannot drift apart:

#include <stdio.h>

int main(void) {
    int scores[3] = {90, 75, 60};
    int count = sizeof scores / sizeof scores[0];
    int total = 0;
    for (int i = 0; i < count; i++) {
        total += scores[i];
    }
    printf("%d\n", total);

    int wanted = 5;
    if (wanted >= 0 && wanted < count) {
        printf("%d\n", scores[wanted]);
    } else {
        printf("no score at %d\n", wanted);
    }
    return 0;
}

Output

225
no score at 5

sizeof scores / sizeof scores[0] works on any array in scope, but not on a pointer. An array passed to a function arrives as a pointer, so the function needs its length as a second argument. The cppreference page on C arrays covers that conversion, and its page on undefined behavior explains why the compiler may assume an out-of-bounds index never happens.

How do I make gcc or clang catch out-of-bounds access?

gcc and clang both catch out-of-bounds access when you build with the sanitizers turned on:

gcc -g -fsanitize=address,undefined -fno-sanitize-recover=undefined main.c -o main
./main

The undefined-behavior sanitizer reports an index past the end of a declared array with the file, line and column, then runtime error: index 5 out of bounds for type 'int [2]'. By default it prints that and carries on; -fno-sanitize-recover=undefined makes it stop there. The address sanitizer catches reads and writes past the end of stack and heap memory, through pointers too, prints ERROR: AddressSanitizer: stack-buffer-overflow or heap-buffer-overflow, and stops the program by default. The gcc instrumentation options list both. Keep them on while you develop and off in the build you ship. Our compiler page uses bounds checks on declared arrays only, so a read past the end of memory from malloc, or through a pointer, is not caught there.

For a warning at compile time, gcc’s -Warray-bounds is part of -Wall, but it only works when optimisation is on, so build with gcc -O2 -Wall. It catches only the indexes the compiler can work out while compiling, such as the 5 in the first example, never one that comes from input.

Python checks every index for you and raises an error instead, covered in IndexError: list index out of range. A segmentation fault from a null pointer in C is a different bug with the same symptom: the address is not past an array, it is no array at all.