那是我的代码:
#include<stdio.h>
int main()
{
int vet[10], i;
for(i=30; i<=45; i++)
{
scanf("%d", &vet[i]);
}
for(i=30; i<=45; i++)
printf(" %d ", vet[i]);
for(i=30; i<=45; i++)
printf(" %x", &vet[i]);
return 0;
}
我在内存上只声明了10个int类型的位置,但是我得到了更多,所以发生了什么? 这是一个内存溢出?
并且类型%x正确打印内存地址?
输入是:
1
2
3
4
5
6
7
8
9
10 /*It was to be stoped right here !?*/
11
12
13
14
15
16
并返回:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 /*I put space to indent*/
22ff6c 22ff70 22ff74 22ff78 22ff7c 22ff80 22ff84 22ff88 22ff8c 22ff90 22ff94 22ff98 22ff9c 22ffa0 22ffa4 22ffa8
答案 0 :(得分:7)
当您访问数组以进行读取或写入时,C语言不会检查边界。程序作者应该确保程序只访问有效的数组元素。
在这种情况下,您将值写入已声明数组的外内存地址。虽然在这种情况下你有时可能会遇到分段违规(SIGSEGV
),但你可能只是“幸运” - 真的,不幸 - 并且在运行时没有遇到任何问题。
答案 1 :(得分:3)
C不强制执行数组边界。保持在限制范围内是你用这种语言的责任 - 它会让你做出明显错误的事情,但它可能会在运行时崩溃。
答案 2 :(得分:3)
C语言不仅没有检查数组大小的数组访问限制,这解释了为什么你成功写入数组15次,但是C也没有将你的范围转换为45到45的机制进入阵列的前10个(或15个?)元素的范围。
所以,你真的试图写入数组vet
的第31到第46个元素,它只有10个元素。
答案 3 :(得分:2)
C不对数组进行边界检查,并且您正在访问一个超出范围的数组。数组中可能的有效索引为[0,9]
,但您正在访问[30,45]
。
您应该修改代码以仅访问有效索引:
int SIZE = 10;
int vet[SIZE];
//...
// not for( i = 30; i <= 45; i++ )
for( i = 0; i < SIZE; ++i ) { /* ... */ }
答案 4 :(得分:2)
C非常乐意让您通过您设置的边界读取和写入数组(在本例中为10)。
阅读超过限制只会给你垃圾;写过去它会做各种疯狂的事情,并且通常会使程序崩溃(或者,如果你运气不好,则覆盖你的整个硬盘)。
你很幸运这个程序,但你不应该继续这样做。在C中,您有责任自己强制执行数组的限制。
答案 5 :(得分:2)
int vet[10]
在内存中声明一个包含十个整数的块。可以通过vet[0]
到vet[9]
访问这些内存位置。通过vet
对内存的任何其他访问都是未定义的行为。绝对任何东西都可以在那个内存中,你很容易破坏程序执行的其余部分。编译器相信你比你正在做的更清楚。
正如@NigelHarper正确指出的那样,%p
是打印指针的官方方式。它以十六进制打印。指针可以用十进制打印,但数字本身没有意义。十六进制使打印更简洁,同样容易看到从一个地址到下一个地址的差异。
也可以使用%x
来打印指针,因为所有操作都是取值并以十六进制格式打印。
答案 6 :(得分:0)
C语言不支持检查超出范围的数组访问。在c ++中,如果您尝试访问超出绑定的数组内存位置,它将生成分段错误,导致您的进程终止。因为,C不允许它,这是预期的行为。