将多维数组作为指向C中函数的指针传递会产生意外结果

时间:2022-09-06 19:38:51

I'm new to C, and I am trying to write a function which counts the number of 1's along each column in a matrix made out of 1's and 0's. Here's my code:

我是C的新手,我正在尝试编写一个函数来计算由1和0组成的矩阵中每列的1的数量。这是我的代码:

#include <stdio.h>

void *countCols(int *output, int rows, int cols, int **matrix[5][5])
{
  /*(int *output) is the pointer which we want the output stored at.
   *(int rows) is the number of rows in our matrix. This is found to be 5 at runtime
   *(int cols) is the number of cols in our matrix. This is also found to be 5 at runtime.
   *(int **matrix[5][5]) is a matrix containing the 1's and 0's.
   */
  int colnum;
  int rownum;
  int counts[cols];
  for (colnum = 0; colnum < cols; colnum ++)
  {
    for (rownum = 0; rownum < rows; rownum ++)
    {
      counts[colnum] += matrix[rownum][colnum];
    }
  }
  /*
   *We store the result in output.
   */
  output = counts;
}

int main(int argc, char **argv)
{
  /*
   *First, we create our matrix.
   */
  int matrix[5][5] = {{0, 1, 1, 0, 1},
                      {1, 0, 1, 1, 0},
                      {1, 0, 0, 0, 1},
                      {0, 0, 1, 1, 1},
                      {1, 0, 1, 1, 0}};
  int *Cs;
  countCols(Cs, 5, 5, matrix); 
  /*Here, we tally up our 1's column by column.*/
  int i;
  printf("The column counts are:\n");
  for (i = 0; i < 5; i ++)
  {
    printf("%d\n", Cs[i]);
    /*Next, we print the counts on separate lines.*/
  }
  /*Finally, we return 0*/
  return 0;
}

So, I was expecting:

所以,我期待:

The column counts are:
3
1
4
3
3

However, to my surprise, I got:

但令我惊讶的是,我得到了:

The column counts are:
1768709983
1935631202
1953653108
1767992671
1600061550

What's going on here? It's also worth noting that, when I compiled, I got these warnings:

这里发生了什么?值得注意的是,当我编译时,我得到了这些警告:

C.c In function 'countCols':
C.c:12.22: warning: assignment makes integer from pointer without a cast
        counts[colnum] += matrix[rownum][colnum];

C.c In function 'main':
C.c:27.23: warning: passing argument 4 of 'countCols' from incompatible pointer type
     countCols(Cs, 5, 5, matrix);

C.c:3:7: note: expected 'int ** (*)[5]' but argument is of type 'int (*)[5]'
 void *countCols(int *output, int rows, int cols, int **matrix[5][5])

Any suggestions would be greatly appreciated.

任何建议将不胜感激。

Edit: Just to be clear, I'm passing a pointer to the matrix, not the matrix itself, into countCols.

编辑:为了清楚起见,我将一个指向矩阵的指针,而不是矩阵本身,传递给countCols。

2 个解决方案

#1


2  

Your function doesn't return anything, so the return type should be void, not void*.

您的函数不返回任何内容,因此返回类型应为void,而不是void *。

First of all the prototype of your function should be something like this:

首先,你的函数的原型应该是这样的:

void countCols(int *output, int rows, int cols, int matrix[5][5])

void countCols(int * output,int rows,int cols,int matrix [5] [5])

it could be improved though.

它可以改善。

Then, inside the body of the function you do:

然后,在你执行的函数体内:

output = counts;

输出=计数;

where you set your pointer to an array that has local scope, thus it will be de-allocate when the function terminates. However, your pointer, Cs, will not preserve changes, since it's passed by value to the function.

您将指针设置为具有本地范围的数组,因此在函数终止时将取消分配。但是,您的指针Cs不会保留更改,因为它通过值传递给函数。

Use dynamic allocation instead and don't forget to free it when you are done.

使用动态分配,不要忘记在完成后释放它。

With dynamic allocation your function should be like this (notice that the prototype differs from the one I suggested above):

通过动态分配,您的功能应该是这样的(注意原型与我上面提到的原型不同):

// Pass a pointer to the integer pointer for 'output'
void countCols(int **output, int rows, int cols, int matrix[5][5])
{
  int colnum;
  int rownum;
  // PERFORM DYNAMIC ALLOCATIONS and USE 'output', instead of 'count'
  *output = malloc(sizeof(int) * cols);
  for (colnum = 0; colnum < cols; colnum ++)
  {
    for (rownum = 0; rownum < rows; rownum ++)
    {
      (*output)[colnum] += matrix[rownum][colnum];
    }
  }

  // NO NEED FOR THIS
  // output = counts;
}

and the main, where the calling and the free-ing of the memory are remarkable:

而主要的,记忆的召唤和释放是显着的:

int main(int argc, char **argv)
{
  /*
   *First, we create our matrix.
   */
  int matrix[5][5] = {{0, 1, 1, 0, 1},
                      {1, 0, 1, 1, 0},
                      {1, 0, 0, 0, 1},
                      {0, 0, 1, 1, 1},
                      {1, 0, 1, 1, 0}};
  int *Cs = NULL;
  countCols(&Cs, 5, 5, matrix);
  /*Here, we tally up our 1's column by column.*/
  int i;
  printf("The column counts are:\n");
  for (i = 0; i < 5; i ++)
  {
    printf("%d\n", Cs[i]);
    /*Next, we print the counts on separate lines.*/
  }

  free(Cs);
  /*Finally, we return 0*/
  return 0;
}

Appendix

附录

As The Paramagnetic Croissant said:

正如The Paramagnetic Croissant所说:

"Pay attention to the warnings. An array is not a pointer, a pointer is not an array, and a multidimensional array is not a pointer-to-pointer."

“注意警告。数组不是指针,指针不是数组,多维数组不是指向指针的指针。”

Make sure you take a good look at the Arrays and Pointers section from here.

请务必仔细查看此处的“数组和指针”部分。

#2


0  

I think you mean the following function declaration:)

我认为你的意思是以下函数声明:)

void countCols(int *output, int rows, int cols, int ( *matrix )[5] );

instead of

代替

void *countCols(int *output, int rows, int cols, int **matrix[5][5]);

because you call it like

因为你称之为

countCols(Cs, 5, 5, matrix); 

Take into account that you did not allocate memory that would be pointed to by pointer Cs

考虑到您没有分配指针Cs指向的内存

int *Cs;

However inside the function you assign it the address of the first element of a local array.

但是在函数内部,您可以为其指定本地数组的第一个元素的地址。

So the program has undefined behaviour.

所以程序有不确定的行为。

You could write simply

你可以写简单

int Cs[5];

and inside the function use it instead of the local array.

在函数内部使用它而不是本地数组。

So remove the definition of the local array

因此删除本地数组的定义

  int counts[cols];

from the function and use directly parameter output

从功能和使用直接参数输出

#1


2  

Your function doesn't return anything, so the return type should be void, not void*.

您的函数不返回任何内容,因此返回类型应为void,而不是void *。

First of all the prototype of your function should be something like this:

首先,你的函数的原型应该是这样的:

void countCols(int *output, int rows, int cols, int matrix[5][5])

void countCols(int * output,int rows,int cols,int matrix [5] [5])

it could be improved though.

它可以改善。

Then, inside the body of the function you do:

然后,在你执行的函数体内:

output = counts;

输出=计数;

where you set your pointer to an array that has local scope, thus it will be de-allocate when the function terminates. However, your pointer, Cs, will not preserve changes, since it's passed by value to the function.

您将指针设置为具有本地范围的数组,因此在函数终止时将取消分配。但是,您的指针Cs不会保留更改,因为它通过值传递给函数。

Use dynamic allocation instead and don't forget to free it when you are done.

使用动态分配,不要忘记在完成后释放它。

With dynamic allocation your function should be like this (notice that the prototype differs from the one I suggested above):

通过动态分配,您的功能应该是这样的(注意原型与我上面提到的原型不同):

// Pass a pointer to the integer pointer for 'output'
void countCols(int **output, int rows, int cols, int matrix[5][5])
{
  int colnum;
  int rownum;
  // PERFORM DYNAMIC ALLOCATIONS and USE 'output', instead of 'count'
  *output = malloc(sizeof(int) * cols);
  for (colnum = 0; colnum < cols; colnum ++)
  {
    for (rownum = 0; rownum < rows; rownum ++)
    {
      (*output)[colnum] += matrix[rownum][colnum];
    }
  }

  // NO NEED FOR THIS
  // output = counts;
}

and the main, where the calling and the free-ing of the memory are remarkable:

而主要的,记忆的召唤和释放是显着的:

int main(int argc, char **argv)
{
  /*
   *First, we create our matrix.
   */
  int matrix[5][5] = {{0, 1, 1, 0, 1},
                      {1, 0, 1, 1, 0},
                      {1, 0, 0, 0, 1},
                      {0, 0, 1, 1, 1},
                      {1, 0, 1, 1, 0}};
  int *Cs = NULL;
  countCols(&Cs, 5, 5, matrix);
  /*Here, we tally up our 1's column by column.*/
  int i;
  printf("The column counts are:\n");
  for (i = 0; i < 5; i ++)
  {
    printf("%d\n", Cs[i]);
    /*Next, we print the counts on separate lines.*/
  }

  free(Cs);
  /*Finally, we return 0*/
  return 0;
}

Appendix

附录

As The Paramagnetic Croissant said:

正如The Paramagnetic Croissant所说:

"Pay attention to the warnings. An array is not a pointer, a pointer is not an array, and a multidimensional array is not a pointer-to-pointer."

“注意警告。数组不是指针,指针不是数组,多维数组不是指向指针的指针。”

Make sure you take a good look at the Arrays and Pointers section from here.

请务必仔细查看此处的“数组和指针”部分。

#2


0  

I think you mean the following function declaration:)

我认为你的意思是以下函数声明:)

void countCols(int *output, int rows, int cols, int ( *matrix )[5] );

instead of

代替

void *countCols(int *output, int rows, int cols, int **matrix[5][5]);

because you call it like

因为你称之为

countCols(Cs, 5, 5, matrix); 

Take into account that you did not allocate memory that would be pointed to by pointer Cs

考虑到您没有分配指针Cs指向的内存

int *Cs;

However inside the function you assign it the address of the first element of a local array.

但是在函数内部,您可以为其指定本地数组的第一个元素的地址。

So the program has undefined behaviour.

所以程序有不确定的行为。

You could write simply

你可以写简单

int Cs[5];

and inside the function use it instead of the local array.

在函数内部使用它而不是本地数组。

So remove the definition of the local array

因此删除本地数组的定义

  int counts[cols];

from the function and use directly parameter output

从功能和使用直接参数输出