函数原型在C中返回2D数组

Noo*_*mer 2 c pointers multidimensional-array function-prototypes

我不是很擅长C而且我对双阵列很困惑.下面是我有一个问题的代码大纲.Main函数调用CreateRandConn函数,并将一个填充0的2D数组作为参数传递给它.CreateRandConn函数将2D数组作为参数,将2DArray中的某些值从0更改为1,并将更改后的2DArray返回给main.我想在函数原型中指出CreateRandConn函数的返回类型是一个2D数组.我该如何表明?我真的不懂语法.我写错了什么?我传递2DArray作为函数头中的参数的方式是不正确的?如果是这样,我怎么写呢?我仍然对指针和双数组之间的关系感到困惑.有人可以用下面的代码大纲来解释它吗?希望有人知道我的问题是什么......

//Function prototype
int ** CreateRandConn(char * RandRoom[7], int my2DArray[7][7], char * room_dir);

//Function
int ** CreateRandConn(char * RandRoom[7], int my2DArray[7][7], char * room_dir)
{
   ...
   return my2DArray;
}

int main()
{
   int 2DArray[7][7] = {0}; 
   2DArray = CreateRandConn(RandRoomArray, my2DArray[7][7], room_dir);
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

alk*_*alk 5

我真的不懂语法.

好的,让我们回顾一下基础知识:

  1. 无法分配给数组变量.
  2. 如果数组传递给函数,它会" 衰减 "到指向其第一个元素的指针.
  3. 多维数组只是一个数组数组.因此,2D阵列是1D阵列的1D阵列,3D阵列是2D阵列的1D阵列,4D阵列是3D阵列的1D阵列,依此类推......
  4. 指向类型元素p数组的指针定义为:NTT (*p)[N]

现在为你举例:

你有

int 2DArray[7][7] = ...;
Run Code Online (Sandbox Code Playgroud)

为了清楚起见,我将其改为

int a[5][7] = ...;
Run Code Online (Sandbox Code Playgroud)

所以这会传递给一个函数.如果发生以下情况/适用:

  • 在上面的1.之后,不可能传递一个数组,好像有可能将它分配给函数内部的变量,因为无法分配数组,无法传递数组.
  • 在上面的2.之后,该函数需要将相关变量定义为" 指向数组第一元素的指针 ".
  • 在上面的3.之后,a第一个元素是int [7]
  • 在上面的4.之后,指向a的指针int[7]将被定义为:int(*)[7].

所以函数的相关变量看起来像:

... func(int (*pa)[7])
Run Code Online (Sandbox Code Playgroud)

pa指向的第一个元素a.作为旁注:从这个指针开始a,函数无法导出a实际"提供"的元素数量,会说:一个a指向后面有多少个有效元素,所以这也需要传递给函数:

... func(int (*pa)[7], size_t rows)
Run Code Online (Sandbox Code Playgroud)

从目前为止我们学到的步骤来看,一个数组没有被传递,但是只传递了它的第一个元素*1指针复制到函数的局部变量(这里).pa

由此直接得出一个数组不能作为函数的返回值传回,而只是一个指向数组元素的指针(通常是第一个)

看看如何定义指向数组的指针:T (*p)[N]我们知道需要派生返回指向数组的指针的函数.函数的defalcation有点需要成为p上述.因此,采取TintN为7,我们再得到:

int (*func(int (*pa)[7], size_t rows))[7];
Run Code Online (Sandbox Code Playgroud)

那么简单的实现和用法将是:

#include <stdlib.h> /* for size_t */

#define ROWS (5)
#define COLS (7)

int (*func(int (*pa)[COLS], size_t rows))[COLS];

int (*func(int (*pa)[COLS], size_t rows))[COLS]
{
  for (size_t i = 0; i < rows; ++i)
  {
    for (size_t j = 0; j < COLS; ++j)  
    {
      pa[i][j] = 0;
    }
  }

  return pa;
}

int main(void)
{
  int a[ROWS][COLS];

  int (*pa)[COLS] = func(a, ROWS);

  return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

*1(虽然草率,但经常被错误地称为" 指向数组的指针被传递 ",一般情况下它不是,但就在这里,因为它是一个2D数组,会说数组的元素本身就是数组).


如果您理解了上述内容,那么仅仅是为了完整性,遵循上述函数声明的不太奇怪的外观(但也可能是教育程度较低;-)).它可以通过使用一个typedef构造来声明,该构造隐藏了数组指针的某种复杂的声明作为参数和返回类型.

这个

typedef int (*PA)[COLS];
Run Code Online (Sandbox Code Playgroud)

定义了一个类型的指示的一个阵列COLSint

所以使用PA我们可以代替

int (*func(int (*pa)[COLS], size_t rows))[COLS];
Run Code Online (Sandbox Code Playgroud)

PA func(PA pa, size_t rows))[COLS];
Run Code Online (Sandbox Code Playgroud)

此版本与上述相同.

是的,它看起来更简单,但带来的事实是,指针pa和函数的返回值)只能通过查看它们的定义而无法识别为指针.许多程序员认为这种结构被认为是"不好的做法".