我正在使用Code :: Blocks 10.05和GNU GCC编译器。
基本上,当我尝试在声明大小之外初始化数组时,我遇到了一个非常奇怪的(对我来说,莫名其妙)问题。用语言来说就是这样:
*有一个声明的大小为[x] [y]的数组。
*还有另一个声明的数组,大小为[y-1]。
尝试将值放入size [y-1]
大小之外的第二个[y-1]
数组时会出现此问题。尝试此操作时,第一个数组[x][y]
将不再保留其所有值。我根本不明白为什么破坏(或试图破坏)一个数组会影响另一个数组的内容。这里有一些示例代码可以看到它发生(它的格式是破碎的。要查看问题消失,只需将array2[4]
更改为array2[5]
(从而消除我所指出的问题)。< / p>
#include <stdio.h>
int main(void)
{
//Declare the array/indices
char array[10][5];
int array2[4]; //to see it work (and verify the issue), change 4 to 5
int i, j;
//Set up use of an input text file to fill the array
FILE *ifp;
ifp = fopen("input.txt", "r");
//Fill the array
for (i = 0; i <= 9; i++)
{
for (j = 0; j <= 5; j++)
{
fscanf(ifp, "%c", &array[i][j]);
//printf("[%d][%d] = %c\n", i, j, array[i][j]);
}
}
for (j = 4; j >= 0; j--)
{
for (i = 0; i <= 9; i++)
{
printf("[%d][%d] = %c\n", i, j, array[i][j]);
}
//PROBLEM LINE*************
array2[j] = 5;
}
fclose(ifp);
return 0;
}
所以有人知道这是怎么发生的?为什么会发生这种情况?
答案 0 :(得分:4)
因为当你在数组边界之外写字时,C允许你。你只是写信给程序中的其他地方。
C被称为最低级别的高级语言。要了解“低级别”意味着什么,请记住,您创建的每个变量都可以被视为生活在物理内存中。如果整数大小为4,则长度为16的整数数组可能占用64个字节。也许它们占用字节100-163(不太可能,但我不会构成实际数字,这些通常也更好地用十六进制表示)。什么占用字节164?也许你的程序中有另一个变量。如果你写一个16个整数的数组之后会发生什么?好吧,它可能会写入该字节。
C可以让你这样做。为什么?如果你想不出任何答案,那么也许你应该转换语言。我不是很迂腐 - 如果这个没有让你受益,那么你可能想要用一种语言来编程,在这种语言中你有点难以犯这样的奇怪错误。但原因包括:
道德是:在C中,要非常小心。您必须检查自己的数组边界。你必须清理自己的记忆。如果你不这样做,你的程序通常不会崩溃,但会开始只是做一些非常奇怪的事情而不告诉你在哪里或为什么。
答案 1 :(得分:2)
for (j = 0; j <= 5; j++)
应该是
for (j = 0; j <= 4; j++)
和array2
最大索引为3
所以
array2[j] = 5;
j == 4
时也会出现问题。
C数组索引从0
开始。因此,[X]
数组有效索引从0
到X-1
,因此您总共获得了X个元素。
您应该使用<
运算符而不是<=
,以便在数组声明[X]
和表达式< X
中显示相同的数字。例如
int array[10];
...
for (i=0 ; i < 10 ; ++i) ... // instead of `<= 9`
这不容易出错。
答案 2 :(得分:1)
如果你超出了一个数组的范围,那么你总是有可能进入另一个数组的范围内。
答案 3 :(得分:1)
array2[j] = 5;
- 这是你的溢出问题。
for (j = 0; j <= 5; j++)
- 这也是溢出问题。在这里,您还尝试访问第5个索引,您只能访问第0到第4个索引。
在进程内存中,在调用每个函数时,将创建一个激活记录以保留函数的所有局部变量,并且还将有更多的内存来存储被调用的函数地址位置。在您的函数中,有四个局部变量array
,array2
,i
和j
。所有这四个都将按顺序排列。因此,如果发生溢出,它将首先尝试覆盖在上面或下面声明的变量,这取决于体系结构。如果更多字节发生溢出,则可能通过覆盖被调用函数的一些局部变量来破坏整个堆栈本身。这也可能导致崩溃,有时它可能不会,但它会像你现在面对的那样表现得无关紧要。