#include <stdio.h>
#include <conio.h>
int main()
{
char b[] = "samuel ricky";
char c[2];
c[0] = 'd';
c[1] = 'a';
c[2] = 'd';
printf("%s\n", b);
getch();
return 0;
}
如果我运行此代码,则输出为:
damuel ricky
如果代码被删除
c[2] = 'd';
输出是:
samuel ricky
如果代码被删除,则结果输出完全没有连接。 它是怎么发生的?
答案 0 :(得分:3)
请使用-Wall
标记启用所有警告,您将在控制台中找到答案:
C02QT2UBFVH6-lm:~ gsamaras$ gcc -Wall main.c
main.c:10:5: warning: array index 2 is past the end of the array (which contains 2 elements) [-Warray-bounds]
c[2] = 'd';
^ ~
main.c:6:5: note: array 'c' declared here
char c[2];
^
1 warning generated.
正如警告所说,你写的内存是你不熟悉的,因为c数组中的索引从0开始,但你似乎已经知道了。
因此char c[2];
有两个单元格,c[0]
和c[1]
。写入c[2]
正在调用未定义的行为,这意味着您在机器中看到的内容现在,明天可能会有所不同,或者在任何其他时间都有所不同机。
总之,现在你机器上发生的事情就是你在写作&#39; d&#39;到c[2]
,它超出范围,恰好写在b[0]
的存储单元中。这就是为什么你看到&#34; damuel ricky&#34;例如,我看到&#34; samuel ricky&#34;。
如果我是你,我wouldn't use conio.h,你可能最终会像苏格拉底......;)
答案 1 :(得分:2)
声明0
为具有索引1
和2
的两个元素的数组分配空间。您对该数组的索引damuel ricky
的写入会调用undefined behavior。
至于为什么你会看到结果+------+------+------+------+ <-- low memory
| c[0] | c[1] | b[0] | b[1] |
+------+------+------+------+
| b[2] | ... |
+------+------+------+------+ <-- high memory
- 许多实现在堆栈上的连续块中分配局部变量(忽略一些必要的填充)。此外,许多调用约定(如cdecl调用约定)将局部变量从高内存分配到低内存,就像这样(回想一下堆栈向低内存增长):
c
因此,访问b
的索引2实际上与访问{{1}}的索引0相同。请注意,这是依赖于实现的,并且您可能不会使用其他编译器或计算机表现出相同的行为。