Reputation:
I have no idea why this code complies :
int array[100];
array[-50] = 100; // Crash!!
...the compiler still compiles properly, without compiling errors, and warnings.
So why does it compile at all?
Upvotes: 2
Views: 877
Reputation: 25927
array[-50] = 100;
Actually means here:
*(array - 50) = 100;
Take into consideration this code:
int array[100];
int *b = &(a[50]);
b[-20] = 5;
This code is valid and won't crash. Compiler has no way of knowing, whether the code will crash or not and what programmer wanted to do with the array. So it does not complain.
Finally, take into consideration, that you should not rely on compiler warnings while finding bugs in your code. Compilers will not find most of your bugs, they barely try to make some hints for you to ease the bugfixing process (sometimes they even may be mistaken and point out, that valid code is buggy). Also, the standard actually never requires the compiler to emit warning, so these are only an act of good will of compiler implementers.
Upvotes: 7
Reputation: 299730
True compilers do (note: need to switch the compiler to clang 3.2, gcc is not user-friendly)
Compilation finished with warnings:
source.cpp:3:4: warning: array index -50 is before the beginning of the array [-Warray-bounds]
array[-50] = 100;
^ ~~~
source.cpp:2:4: note: array 'array' declared here
int array[100];
^
1 warning generated.
If you have a lesser (*) compiler, you may have to setup the warning manually though.
(*) ie, less user-friendly
Upvotes: 1
Reputation: 437326
It compiles because the expression array[-50]
is transformed to the equivalent
*(&array[0] + (-50))
which is another way of saying "take the memory address &array[0]
and add to it -50 times sizeof(array[0])
, then interpret the contents of the resulting memory address and those following it as an int
", as per the usual pointer arithmetic rules. This is a perfectly valid expression where -50
might really be any integer (and of course it doesn't need to be a compile-time constant).
Now it's definitely true that since here -50
is a compile-time constant, and since accessing the minus 50th element of an array is almost always an error, the compiler could (and perhaps should) produce a warning for this.
However, we should also consider that detecting this specific condition (statically indexing into an array with an apparently invalid index) is something that you don't expect to see in real code. Therefore the compiler team's resources will be probably put to better use doing something else.
Contrast this with other constructs like if (answer = 42)
which you do expect to see in real code (if only because it's so easy to make that typo) and which are hard to debug (the eye can easily read =
as ==
, whereas that -50
immediately sticks out). In these cases a compiler warning is much more productive.
Upvotes: 6
Reputation: 62048
The compiler is not required to catch all potential problems at compile time. The C standard allows for undefined behavior at run time (which is what happens when this program is executed). You may treat it as a legal excuse not to catch this kind of bugs.
There are compilers and static program analyzers that can do catch trivial bugs like this, though.
Upvotes: 1
Reputation: 1422
The number inside the brackets is just an index. It tells you how many steps in memory to take to find the number you're requesting. array[2]
means start at the beginning of array, and jump forwards two times.
You just told it to jump backwards 50 times, which is a valid statement. However, I can't imagine there being a good reason for doing this...
Upvotes: 0