int main()
{
int i;
int vals[5];
for (i = 0; i <= 5; i++)
{
vals[i] = 0;
}
printf("%d\n", i);
return 0;
}
我正在尝试从大学教程中学习C语言。他们在上面的代码中提到:
当我达到5时,for循环重置,程序再次循环,然后重复循环。
我无法理解为什么,我试图在pythontutor.com中弄清楚它给出了6
(现在是C的实验)。适当的输出是什么以及为什么会出现这种情况?
答案 0 :(得分:6)
C中的数组索引是基于0的。因此,如果您的数组大小为5,则索引从0到4。
循环for (i = 0; i <= 5; i++)
到达索引5,它超出了数组的范围。
超出缓冲区边界是C中的未定义行为。允许任何事情发生。而你的程序完全失败,是一个可能的结果。
可能正在发生,因为数组和索引在内存中彼此相邻。因此vals[5] = 0
将i
设置为零。从此以后,循环条件永远得到满足。
答案 1 :(得分:5)
此代码调用未定义的行为。 这当然意味着他们所说的,可能实际发生。但这很大程度上取决于许多细节。
当他们声明i
将被重置时,他们会假设堆栈上的某个变量位置。
一旦执行
vals[i] = 0;
使用i==5
您可以实际写入存储i
的位置。但另一方面,i
只能保存在寄存器中或堆栈中的其他位置,您将无法获得无限循环。
答案 2 :(得分:0)
具有automatic storage class
的变量(在除static variables
之外的函数中创建的变量)是在C
编程语言的堆栈中创建的。
程序中的变量也是在堆栈中创建的。因此,变量i
,vals[0]
,vals[1]
,vals[2]
,vals[3]
和vals[4]
可以在堆栈中找到。
请记住:C programming language
中的数组索引从0
开始。如果数组的大小为n
,则索引从0到(n-1)。
当您的索引变量达到for
时,程序中的5
循环正在尝试访问val [5]。到达数组范围之外的是C中的 UNDEFINED BEHAVIOR 。您看到的结果是可能的结果之一。由于您的堆栈中不存在vals[5]
,因此您可能正在访问分配给某个其他变量的内存位置,该变量可能是分配给变量i
的内存位置。你甚至可以获得分段错误,如果你访问一个数组超出它的界限(正如我上面提到的,结果是未定义的。你的程序可以运行而没有任何分段错误,或者你可能得到它)。 / p>
考虑一下我创建的图片:
在您的情况下,数组(vals)和索引(i)可能在堆栈中彼此相邻。因此,vals[5] = 0
将i重置为零,因此无限循环。