为了账号安全,请及时绑定邮箱和手机立即绑定

声明C函数以返回数组

声明C函数以返回数组

C
catspeake 2019-07-25 14:14:27
声明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);}
查看完整描述

3 回答

?
喵喵时光机

TA贡献1846条经验 获得超7个赞

有几件事要指出。

首先,不能像在这里那样分配数组对象:

char A[WIDTH][HEIGHT];  A=rand_grid(WIDTH,HEIGHT);

数组类型的对象是不可修改的。

其次,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;}

语法有点混乱,它是

       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 arraychar (*foo(int width))[HEIGHT]               -- of char

对于C89,上述代码段中的高度必须是编译时常量积分表达式(宏、数字文字或由宏和/或数字文本组成的算术表达式)。我不确定C99是否也是这样。

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

void foo (T *p) {...}...T arr[N];foo(arr);

对于二维数组,它有点丑:

void foo (T (*p)[M]) {...}...T arr[N][M];foo(arr);

这还依赖于编译时已知的M,这限制了函数的有用性。您想要的是一个可以处理任意大小的二维数组的函数。我所知道的实现这一目标的最佳方法是将指针传递到数组,传递数组中第一个元素的地址[1],并将行数和列数作为单独的参数传递:

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

所以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);
  ...}

  1. 即使这些表情

    &A[0][0]

    A

    产生相同的值(A的基址),这两个表达式的类型是不同的。第一个表达式计算为指向char的简单指针(

    char *

    ),而第二个值计算为指向char的二维数组的指针(

    char (*)[HEIGHT]).



 


查看完整回答
反对 回复 2019-07-26
?
守着星空守着你

TA贡献1799条经验 获得超8个赞

您永远不能返回已分配的堆栈(“auto“)非原始(值)类型的变量,以及struct是这样的。对于其他类型,您需要从堆中分配内存,使用malloc(),或将(固定大小)数组包装为struct.

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

#define WIDTH  11#define HEIGHT 11typedef 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;}

这很好,而且不应该比使用显式指针的代价更高:

void board_init(Board *b);

因为前者的struct-back可以重写(由编译器)到后者。这叫做返回值优化.




查看完整回答
反对 回复 2019-07-26
  • 3 回答
  • 0 关注
  • 356 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信