C修改数组意外行为

时间:2014-04-08 20:25:52

标签: c arrays

我理解不可能将数组传递给C中的函数并修改它而不使用发送对该数组的引用,那么国际象棋方法如何初始化数组,并且正在主数据中正确打印? / p>

int chess(int rows, int cols, int array[rows][cols])
{

  /* Go through the rows and colums in the array */
  for (int i = 0; i < rows;i++)
  {

    for (int j = 0; j < cols; j++)
    {
      /* If the location is even, then print a 0, else print a 1. */
      if (((i + j) % 2) ==0)
      {
        array[i][j] = 0;
      }
      else
      {
        array[i][j] = 1;
      }
    }
  }
  /* return */
  return 0;

}

int main(void)
{
  int arrayDimensions;

  int noOfTests = 7;

  /* run the program for the given amount of tests */
  /*for (arrayDimensions = 0; arrayDimensions <= noOfTests; arrayDimensions++)*/
  {
    /* Declare an array for each dimension */
    int array[6][5];

    /* call the chess method passing it the arguments specified. */
    chess(6, 5, array);

    /* Print out the array according to the size of the array. */
    for (int i = 0; i < 6; i++)
    {
      printf("\n");
      for (int j = 0; j < 5; j++)
      {
        printf("%d", array[i][j]);
      }

    }
    /* Create a new line after each row */
    printf("\n");

  }

}

4 个答案:

答案 0 :(得分:3)

虽然你可能已经知道了大部分内容,但后一部分是相关的,所以请坚持一下。

您可能知道的内容

C是一种按值传递的语言。这意味着当你这样做时:

void foo(int x)
{
    x = 5;
}

称为

int n = 1;
foo(n);
printf("%d\n", n); // n is still 1

调用者传递一个值,参数x接收它。但是更改x对调用者没有影响。如果要修改调用者的数据变量,则必须通过 - 地址执行此操作。您可以通过将形式参数声明为指向类型的指针,取消引用指针来修改指向的数据,最后传递变量的地址来修改:

void foo(int *p)
{
    *p = 5;
}

称为:

int n = 1;
foo(&n);
printf("%d\n", n); // n is now 5

你为什么关心?

那么任何与你的数组有什么关系呢? C中的数组是数组底层类型的连续数据序列,数组的表达式 value 是其第一个元素的地址

在最后一句话上咀嚼一分钟。这意味着int变量具有存储在其中的int值的方式相同,数组变量将其第一个元素的地址作为其“值”。到现在为止,您知道指针包含地址。知道这一点以及之前的描述意味着:

int ar[10];
int *p = ar;

是合法的。 ar的“值”是它的第一个元素地址,我们将该地址分配给指针p

好的,所以语言专门定义数组为参数,只是指向它们的第一个元素。因此,这两者都是等价的:

void foo(int *p)
{
    *p = 5;
}

void bar(int ar[])
{
    ar[0] = 5;
}

来电方:

int ar[10];
foo(ar); // legal, ar's "value" is its first element address
bar(ar); // legal, identical to the above.

在解释指针和数组的基本原理时,我常常使用的一句话就是:

  

指针是持有地址的变量;数组是 地址的变量。


那么这种破坏性的语法怎么样?

<强> int chess(int rows, int cols, int array[rows][cols])

阿。有一些有趣的东西。您的编译器支持VLA s (variable length arrays)。在编译此函数的代码时,编译器会生成适当的逻辑以执行对传递的数组的正确访问。即它知道这个:

array[1][0]

cols超过数组开头的int个值。如果没有VLA的特性(并且某些C编译器没有它们),您必须自己手动进行逐行数学运算。不是不可能的,而是单调乏味的。我只是简单地提到C ++不支持VLA; C语言没有的少数几个特性之一。


<强>摘要

数组是按地址传递的,因为当涉及到它们的“价值”时,就是所有的:地址

注意:我非常努力地避免在本说明中使用“衰变”或“衰减到指针”这个词,因为动词意味着一些神秘的功能操作当实际上不存在时。数组不会“衰减”到任何。他们只是;根据C标准,它们的“价值”是它们的第一个元素的地址。期。您使用该地址做的内容是另一回事。并且作为一个地址,指针可以保存它们的“值”并取消引用以访问所述相同的(例如函数参数)。

个人:我曾经在这个论坛上问过这个术语(衰变)在C-engineer白话中有多长时间被嗡嗡声,因为在C标准的600多页中它看起来完全是ZERO次。任何人发现的最远的后面是1988年在一些显眼的在线期刊的编年史。我总是好奇地注意到谁开始了这个地方,然后说 - 任务继续让我望而却步。

无论如何,我希望这会有所帮助,甚至一点点。

答案 1 :(得分:1)

处理数组时,你正在处理一个地址,所以如果你把一个数组传递给一个函数并且你在函数中改变了数组,那么真正的数组就会改变。 换句话说,如果您知道pointers,则数组是指针。 我没有阅读代码,但你明确误解了将数组传递给函数。

答案 2 :(得分:0)

数组引用是一个地址(说它是指针的用词不当,但它会表现如此)。它的工作原理是因为声明函数接受一种int [] []类型,它允许函数与数组引用进行交互,就好像你传递了一个指向函数的指针一样。

答案 3 :(得分:0)

参考手册:

  

当函数参数声明为数组时,编译器会处理   声明作为指向数组第一个元素的指针。对于   例如,如果x是一个参数并且旨在表示一个数组   整数,它可以声明为以下任何一个声明:

     

int x []; int * x; int x [10];

所以你传递了一个参考文献。编译器将您的声明转换为指针引用,同时还有一些大小限制。