可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Sorry if this is a noob question :( .
Piece of C code.
int array[5];
int cnt;
for(cnt = 0; cnt <= 10; cnt+=1)
{
array[cnt] = cnt;
}
Should give an error, right? No! Works fine!
But why is that? It seems that -in the first line- an array of more than the double size (11) is defined. You can even access array[5 to 10] later on. And that is confusing me. It stops working when you define array[4 or less] ...
Thanks in advance.
回答1:
It may happen to work with your particular compiler and computer, but you shouldn't count on it.
The behaviour of your code according to the C language specification is undefined. This means that it might do what you hope, or it might cause your computer to crash, or it might cause demons to fly out your nose.
Unlike higher-level languages such as Java and C#, C trusts you and does not perform explicit checks on the bounds of arrays. You are supposed to be responsible and not tread outside the boundaries of the array.
回答2:
This only "works" if your definition of "works" is synonymous with "hasn't crashed yet".
回答3:
What you are seeing is undefined behaviour, caused by you accessing the array with an invalid index. Undefined behaviour means that anything could happen, including your program appearing to work correctly.
回答4:
"But why is that?"
Because that's the way C is.
Array bounds are not checked at run time.
That's the "Law of the C"
回答5:
I just like to point out that all this is indeed undefined.
Your example "works" in this specific example because both variables are located on the stack. That is the address of cnt is just below the end of the array. When cnt reaches cnt==5
the statement array[cnt]=cnt; does not write in the memory dedicated to the array but just after it, where the address of cnt lay. It is just luck that it does not alter your counter.
When cnt>5 there is no memory to trash and it will just write in the "stack void" (don't know the proper word).
another example to illustrate this:
int main(int ac,char **av)
{
int a[5];
int cnt;
int cnt2=3;
for(cnt=0;cnt<7;cnt++) {
a[cnt]=cnt;
printf("%d %d %d\n", a[cnt], cnt, cnt2);
}
}
output:
0 0 3
1 1 3
2 2 3
3 3 3
4 4 3
5 5 5
6 6 5
The last two writes of the loop overwrites the stack data after a[] and may yield very confusing errors. In this case the cnt2 is trashed.
回答6:
Arrays in C are not checked at runtime. In other words, you can "define" an array of size N and happily access off of the end of the array bound. If you go off the end of the array, then you will trash memory somewhere on the stack (or the heap).
Once you trash memory somewhere, your program is likely to crash. These crashes can be hard to track down because they might crash far away from where you actually overran the end of the array.
Typically when you declare arrays in C, it's best to use some sort of constant or #define to mark the size of the array:
#define MAX_ELEMENTS 10
int array[MAX_ELEMENTS];
int cnt;
for(cnt = 0; cnt < MAX_ELEMENTS; cnt+=1) {
array[cnt] = cnt;
}
If you go past MAX_ELEMENTS in the array assignment, you might overwrite the value of cnt. You might overwrite some other variable. All depends on the compiler and the code structure. Also note the use of the < sign in the for loop. C arrays are 0 based so you have to check using less-than and not less-than-or-equal-to.
回答7:
Array bounds in C are not necessarily checked at runtime. The standard leaves implementors free to do so if they choose, or not - that's part of what is undefined. On an implementation with fat pointers the sample might indeed cause some sort of error.
回答8:
Once you run off the end of the array, you are overwriting memory that the software is not expecting and corrupting the heap. You software may continue to run, but it will be very unstable!
回答9:
Depends on how the stack memory is packed. Also, it will happily overwrite those values and even read them, but most likely you are corrupting the stack.