Welcome to Software Development on Codidact!
Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.
Comments on Is it undefined behaviour to just make a pointer point outside boundaries of an array without dereferencing it?
Parent
Is it undefined behaviour to just make a pointer point outside boundaries of an array without dereferencing it?
I have heard that it is undefined behaviour to make a pointer point outside boundaries of an array even without dereferencing it. Can that really be true? Consider this code:
int main(void)
{
char arr[10];
char *ptr = &arr[-1];
char c = *ptr;
}
The line char c = *ptr
is obviously bad, because it's accessing out of bounds. But I heard something that even the second line char *ptr = &arr[-1]
invokes undefined behaviour? Is this true? What does the standard say?
Post
When a compiler encounters the statements
char arr[10];
char *ptr = &arr[-1]
there are three things that it could reasonably do:
-
It can raise an error.
-
It can compile the statements and raise a warning.
-
It can compile the statemnts silently.
I think that, in cases 2 and 3, everyone would agree that the value placed in ptr
should be such that
ptr + i == &arr[i - 1]
whenever i - 1
is a valid index of arr
.
I assume that when the language specification says that the compiler's behaviour is undefined it means that the compiler designer is free to choose from these three options.
Although ptr would hold an invalid pointer value there are plausible situations where this would be useful. One example is simulating an array with a non-zero lower bound:
&ptr[1] == &arr[0]
I can think of two reasons for the compiler to generate a warning or error. The first is to draw the programmer's attention to a simple mistake in the "typing error" category. Perhaps he (or she) meant
arr[1]
or arr[N-1]
.
Here I think it is worth comparing &arr[-1]
with the equivalent arr - 1
.
Although these are technically equivalent they are conceptually distinct. The former applies an invalid index to an array, then takes the address of the (non-existent) element. The latter is just a normal pointer arithmetic expression.
The fact that clang gives a warning for the former but passes the latter silently indicates that the clang designers recognised this distinction.
The second, more serious, reason for rejecting this code is that it may result in genuinely undefined behaviour when the program is run. In a general-purpose computer with a large address space this is unlikely, but in a microcontroller system the address of arr may be close to zero. (It can never actually be zero as this has a special meaning.) In that situation subtracting from a pointer could cause an arithmetic overflow, even if the pointer is never dereferenced.
To sum up, although the compiler may accept it and the resultant program do what you expect, it is better to avoid assigning illegal values to pointers. Even if it appears that you could make your code more efficient the compiler's optimiser will probably do a better job, and it will take account of the vagaries of the target hardware.
1 comment thread