我不明白为什么我能这样做:
#include "stdio.h"
#include "string.h"
char a[1][100];
void main(void) {
strcpy(a[0], "test1");
strcpy(a[1], "test2");
strcpy(a[6], "test3");
printf("%s", a[0]);
printf("%s", a[1]);
printf("%s", a[6]);
}
将返回:
test1test2test3
根据我的理解,当我char a[1][100]
时,我创建了一个带有2个元素的{2}数组a[0]
和a[1]
,每个元素指向100个字符的数组。
为什么我可以为a[6]
分配任何内容?难道不该出界吗?记忆在哪里?
感谢您清理它。
答案 0 :(得分:6)
是的,它是出界的,但你期待发生什么?
strcpy(a[6], "test3");
将覆盖堆栈的一部分。它会引起问题吗?大概。它会立即明显吗?可能不是。
答案 1 :(得分:2)
实际上,您只需创建一个只包含一个元素a[0]
的2D数组。 a[1]
和a[6]
都在访问您不拥有的内存,并会导致未定义的行为。 "未定义"并不意味着"会崩溃",这意味着" undefined",包括它的工作原理就像你已经正确分配了东西一样。您偶然使用的内存不会与其他内容发生冲突,因此您的错误不会产生任何后果。
答案 2 :(得分:1)
C即使在编译时也没有任何边界检查。如果你很幸运
int a[5];
a[10] = 10;
会生成警告。一般来说,使用编译器给你的尽可能多的警告进行编译是一个好主意。
可悲的是,我可以从代码中获取gcc的唯一内容是'main必须具有返回类型int'。使用IBM的编译器,我确实得到了这个:
"bad.c", line 8.14: 1506-1299 (W) The subscript 1 is out of range. The only valid subscript is 0.
"bad.c", line 8.14: 1506-1299 (W) The subscript 1 is out of range. The only valid subscript is 0.
"bad.c", line 9.14: 1506-1299 (W) The subscript 6 is out of range. The only valid subscript is 0.
"bad.c", line 9.14: 1506-1299 (W) The subscript 6 is out of range. The only valid subscript is 0.
"bad.c", line 12.20: 1506-1299 (W) The subscript 1 is out of range. The only valid subscript is 0.
"bad.c", line 13.20: 1506-1299 (W) The subscript 6 is out of range. The only valid subscript is 0.
此时,正如一些评论所指出的那样,您处于未定义行为的领域。因为您在堆栈上创建了一个巨大的数组,所以没有任何不好的事情发生。
其他要点:
C数组基于0。 a[1]
创建一个包含一个成员a[0]
。
int a[5][5]
分配30个字的空格,并给a
一个[0] [0]的地址。通过将x乘以5来访问a [x] [y],添加y并查看该位置。不是通过查看[x]的内容,并从中查找y位置。