声明C函数以返回数组

Jas*_*ska 46 c

如何创建一个返回数组的函数?我试过这个

const int WIDTH=11;
const int HEIGHT=11;

int main() {
  char A[WIDTH][HEIGHT];
  A=rand_grid(WIDTH,HEIGHT);
  return 0;
}

// Initializes a random board.
char[][] rand_grid(int i, int k) {
  char* A[i][k];
  for(j=0;j<i;++j) {
    for(l=0;l<k;++l) {
      A[j][l]=ran(10);
    }
  }
  return A;
}

// Returns a random number from the set {0,...,9}.
int ran(int i) {
  srand((unsigned int) time(0));
  return(rand()%10);
}
Run Code Online (Sandbox Code Playgroud)

Joh*_*ode 78

有几点需要指出.

首先,您不能像在此处那样分配数组对象:

char A[WIDTH][HEIGHT];  
A=rand_grid(WIDTH,HEIGHT);
Run Code Online (Sandbox Code Playgroud)

数组类型的对象不可修改.

其次,C中的函数不能返回数组类型.但它们可以返回指向数组的指针:

char (*foo(int width))[HEIGHT]
{
  /**
   * dynamically allocate memory for a widthxHEIGHT array of char
   */
  char (*newArr)[HEIGHT] = malloc(sizeof *newArr * width);
  /**
   * initialize array contents here
   */
  return newArr;
}
Run Code Online (Sandbox Code Playgroud)

语法有点令人困惑; 它读作

       foo                                   -- foo
       foo(int width)                        -- is a function
                                             -- taking an int parameter
      *foo(int width)                        -- returning a pointer
     (*foo(int width))[HEIGHT]               -- to a HEIGHT-element array
char (*foo(int width))[HEIGHT]               -- of char
Run Code Online (Sandbox Code Playgroud)

对于C89,上面代码段中的HEIGHT必须是编译时常量整型表达式(宏,数字文字或由宏和/或数字文字组成的算术表达式).我不确定C99是否也是如此.

根据您发布的代码段,您要做的是获取已分配的数组并初始化其内容.请记住,在大多数上下文中,数组类型的表达式将隐式转换为指向基类型的指针.IOW,如果将N的N元素数组传递给函数,函数实际接收的是指向T的指针:

void foo (T *p) {...}
...
T arr[N];
foo(arr);
Run Code Online (Sandbox Code Playgroud)

对于二维阵列,它有点丑陋:

void foo (T (*p)[M]) {...}
...
T arr[N][M];
foo(arr);
Run Code Online (Sandbox Code Playgroud)

这也依赖于M在编译时已知,这限制了函数的有用性.你想要的是一个可以处理任意大小的二维数组的函数.我知道要做到这一点的最好方法是不是将指针传递给数组,而是传递数组[1]中第一个元素的地址,并将行数和列数作为单独的参数传递:

void foo(T *base, size_t rows, size_t cols) {...}
...
T arr[N][M];
foo (&arr[0][0], N, M);
Run Code Online (Sandbox Code Playgroud)

所以你的rand_grid函数看起来像这样:

void rand_grid(char *base, size_t rows, size_t cols)
{
  size_t i, j;
  for (i = 0; i < rows; i++)
  {
    for (j = 0; j < cols; j++)
    {
      /**
       * Since base is a simple char *, we must index it
       * as though it points to a 1-d array.  This works if
       * base points to the first element of a 2-d array,
       * since multi-dimensional arrays are contiguous.  
       */
      base[i*cols+j] = initial_value();
    }
  }
}

int main(void)
{
  char A[WIDTH][HEIGHT];
  rand_grid(&A[0][0], WIDTH, HEIGHT);
  ...
}
Run Code Online (Sandbox Code Playgroud)
  1. 即使表达式&A[0][0]A产生相同的值(A的基址),两个表达式的类型也不同.第一个表达式求值为一个指向char(char *)的简单指针,而第二个表达式求值为一个指向char()的二维数组的指针char (*)[HEIGHT].

  • 这种反应非常有教育意义.谢谢! (2认同)

Mic*_*ker 15

你不能.您可以将指向数组的指针作为参数传递,并让函数对其进行修改,或者函数本身可以分配数据并返回指针.

在你的情况下

void rand_grid(char A[WIDTH][HEIGHT]) {
    A[0][0] = 'A'; // or whatever you intend to do
}

main() {
    char A[WIDTH][HEIGHT];
    rand_grid(A);
}
Run Code Online (Sandbox Code Playgroud)

编辑:正如caf指出的那样,人们实际上可以在其中返回struct一个数组,但当然没有正确思维的程序员能够做到这一点.

  • 你可以通过将它包装在`struct`中来实际返回数组,但这是一个非常糟糕的主意. (3认同)
  • 为什么在结构中返回数组是个坏主意?将小阵列打包成结构并不罕见.它可能比mallocing内存并返回一个指针更快,更容易. (3认同)

unw*_*ind 11

你永远不能返回一个堆栈分配(" auto")变量,而不是一个原始(值)类型的变量struct.对于其他类型,您需要从堆中分配内存,使用malloc()或将(固定大小)数组包装到一个struct.

如果您使用的是固定大小的数组,则可以将其建模为a struct并使用struct-return:

#define WIDTH  11
#define HEIGHT 11

typedef struct {
  unsigned char cell[WIDTH * HEIGHT];
} Board;

Board board_new(void)
{
  Board b;
  size_t i;

  for(i = 0; i < sizeof b.cell / sizeof *b.cell; i++)
    b.cell[i] = rand() & 255;
  return b;
}
Run Code Online (Sandbox Code Playgroud)

这很好,并且使用显式指针不应该比替代方案更昂贵:

void board_init(Board *b);
Run Code Online (Sandbox Code Playgroud)

由于前一个struct-return的情况可以被(由编译器)重写为后者.这称为返回值优化.

  • 这不是真的 - 你可以返回`struct`类型,它们绝对是非原始的.不过,这不是一个好主意. (3认同)