声明大小为[x] [y]的数组和另一个大小为[y-1]的数组

时间:2012-06-22 03:42:03

标签: c arrays

我正在使用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;

}

所以有人知道这是怎么发生的?为什么会发生这种情况?

4 个答案:

答案 0 :(得分:4)

因为当你在数组边界之外写字时,C允许你。你只是写信给程序中的其他地方。

C被称为最低级别的高级语言。要了解“低级别”意味着什么,请记住,您创建的每个变量都可以被视为生活在物理内存中。如果整数大小为4,则长度为16的整数数组可能占用64个字节。也许它们占用字节100-163(不太可能,但我不会构成实际数字,这些通常也更好地用十六进制表示)。什么占用字节164?也许你的程序中有另一个变量。如果你写一个16个整数的数组之后会发生什么?好吧,它可能会写入该字节。

C可以让你这样做。为什么?如果你想不出任何答案,那么也许你应该转换语言。我不是很迂腐 - 如果这个没有让你受益,那么你可能想要用一种语言来编程,在这种语言中你有点难以犯这样的奇怪错误。但原因包括:

  • 它越来越快。添加边界检查需要时间和空间,因此如果您正在为微处理器编写代码或编写JIT编译器,速度和大小确实很重要。
  • 如果您想了解机器架构并进入硬件,例如如果您是学生,那么它是从编程到OS /硬件/电气工程的良好途径。还有很多计算机科学。
  • 接近机器代码,它的标准是许多其他语言和系统必须或可以轻松地支持某种程度的兼容性。
  • 如果我真的不得不在机器代码附近工作,我可以给出的其他原因。

道德是:在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]数组有效索引从0X-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个索引。

在进程内存中,在调用每个函数时,将创建一个激活记录以保留函数的所有局部变量,并且还将有更多的内存来存储被调用的函数地址位置。在您的函数中,有四个局部变量arrayarray2ij。所有这四个都将按顺序排列。因此,如果发生溢出,它将首先尝试覆盖在上面或下面声明的变量,这取决于体系结构。如果更多字节发生溢出,则可能通过覆盖被调用函数的一些局部变量来破坏整个堆栈本身。这也可能导致崩溃,有时它可能不会,但它会像你现在面对的那样表现得无关紧要。