The Element Doesn’t Exist

As a mid-level language, C has just as many positives as negatives with regards to accessing memory. One of the biggest negatives is C’s unflinching capability to access data that doesn’t exist.

Consider the following code:

#include <stdio.h>

int main()
{
    int b[] = { 2 ,3 };

    printf("%d, %d\n",b[0],b[1]);

    return(0);
}

Line 5 defines a two-element integer array, b[]. The first element (b[0]) is value 2, the second (b[1]) is 3. Both values are output when the program runs:

2, 3

A reader was presented with a puzzle that added another line to the code: b[3] = 10; The code then ran a loop to display the first four elements of array b[]. Here’s the update:

#include <stdio.h>

int main()
{
    int b[] = { 2 ,3 };
    int x;

    b[3] = 10;
    for(x=0;x<4;x++)
        printf("%d\n",b[x]);

    return(0);
}

Array b[] is declared at Line 5 with 2 elements. You cannot re-size an array as the program runs, but you can pull a stunt like b[3] = 10;. The compiler may catch such an error with an “array index is out of bounds” warning. Yes, it’s only a warning and not every compiler generates it. Even so, because it’s just a warning, the code compiles and runs:

2
3
-677642094
10
Abort trap: 6

The Abort trap error is unique to the Macintosh. In both Ubuntu Linux and Code::Blocks running MinGW in Windows 10, the output lacked any error message. The value 10 is shown for the phantom fourth element and random garbage appears for the third.

This code is patently dangerous. The program it generates is unsafe. The question the reader asked me was with regards to the third element, b[2], which isn’t defined in the code but present in the output. I explained that the value is garbage, whatever junk data was already in memory when the program runs. The problem is that the garbage data, as well as the b[3] element, aren’t available as allocated storage for the program to use. The only reason the thing works is because C is a mid-level language and the compiler isn’t strict about forbidding such access.

In my mind, I’m still puzzled as to why the compiler just wouldn’t error on such a declaration and not generate the code. I’m trying to think of a valid reason why you would want to access an undefined array element or how such an operation would prove necessary. I can’t think of a justification.

Consider this code:

#include <stdio.h>

int main()
{
    int b[1];
    int x;

    for(x=0;x<10;x++)
        printf("%d\n",b[x]);

    return(0);
}

An array must be declared with a size or initialized to specific values. You can’t declare an array as b[], so above I declared b[] to be a one-element array. It’s uninitialized. Yet, the for loop plows through 10 elements as if they exist. No errors are warnings are generated by compiling and linking. No error appears in the output, which is just 10 lines of whatever garbage values exist in memory.

No other programming language that I’m aware of would let you output array elements that don’t exist. Yet C seems to be okay with it. The code isn’t valid and the program that runs is unsafe. Therefore, the burden is always on you, the coder, to ensure that your C program accesses only variables and storage that have been allocated and initialized.

Leave a Reply