首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >返回VLA和用法

返回VLA和用法
EN

Stack Overflow用户
提问于 2015-05-25 12:15:05
回答 3查看 799关注 0票数 2

我的职能如下:

代码语言:javascript
复制
int* create_matrix_2(int rows, int cols)
{
    double (*A)[rows][cols] = malloc(sizeof(int[rows][cols]));

    for (int row = 0; row < rows; row++)
    {
        for (int col = 0; col < cols; col++)
        {
            *A[row][col] = row * cols + col;
        }
    }

    for (int row = 0; row < rows; row++)
    {
        for (int col = 0; col < cols; col++)
        {
            printf("%lf, " , *A[row][col]);
        }
        printf("\n");
    }
    return A;
}

我的问题是:如何从该函数返回VLA,类型是什么,如何将其写入函数签名,以及如何在接收返回的数组时使用它?

现在我正试着这样做:

代码语言:javascript
复制
int (*matrix2)[height][width] = create_matrix_2(height, width);

for (int row = 0; row < height; row++)
{
    for (int col = 0; col < width; col++)
    {
        printf("%d" , (*matrix2)[row][col]);
    }
    printf("\n");
}

然后运行:gcc 2d_array_test.c -o 2d_array_test.out -std=c99 -O0

但这会导致以下问题:

代码语言:javascript
复制
2d_array_test.c: In function ‘main’:
2d_array_test.c:35:34: warning: initialization from incompatible pointer type [enabled by default]
  int (*matrix2)[height][width] = create_matrix_2(height, width);
                                  ^
2d_array_test.c: In function ‘create_matrix_2’:
2d_array_test.c:105:2: warning: return from incompatible pointer type [enabled by default]
  return A;
  ^

EDIT#1:

我试着使用alk建议的代码,但是在编译时它会给我带来很多错误。下面是一个单独的程序,它包含您建议的具有一个主要函数的代码:http://pastebin.com/R6hKgvM0 I得到以下错误:

代码语言:javascript
复制
2d_array_test_new.c: In function ‘main’:
2d_array_test_new.c:18:2: warning: passing argument 3 of ‘create_matrix’ from incompatible pointer type [enabled by default]
  if (-1 == create_matrix(height, width, &matrix))
  ^
2d_array_test_new.c:10:5: note: expected ‘int **’ but argument is of type ‘int (**)[(sizetype)(height)][(sizetype)(width)]’
 int create_matrix(size_t, size_t, int**);
     ^
2d_array_test_new.c: At top level:
2d_array_test_new.c:37:5: error: conflicting types for ‘create_matrix’
 int create_matrix(size_t rows, size_t cols, int(**a)[rows][cols])
     ^
2d_array_test_new.c:10:5: note: previous declaration of ‘create_matrix’ was here
 int create_matrix(size_t, size_t, int**);
     ^
2d_array_test_new.c: In function ‘create_matrix’:
2d_array_test_new.c:45:11: error: ‘EINVAL’ undeclared (first use in this function)
   errno = EINVAL;
           ^
2d_array_test_new.c:45:11: note: each undeclared identifier is reported only once for each function it appears in
2d_array_test_new.c:40:6: warning: variable ‘errno’ set but not used [-Wunused-but-set-variable]
  int errno;
      ^

这些错误主要是关于返回类型的。如何正确地编写该数组的类型?

EN

回答 3

Stack Overflow用户

发布于 2015-05-25 12:54:03

首先,您的代码有一些问题。您有一个双数组指针指向一个2D数组的ints,这是没有任何意义的。

而且,由于A是指向2D数组的指针,所以不能执行*A[row][col]。因为[]具有比*更高的优先级,所以代码等同于*(A[row][col])。它的意思是“给我2D矩阵的row数,然后.”。这段代码最终将远远超出界限。

在声明指向动态分配的多维数组的数组指针时,诀窍是忽略最内部的维度。这样,您就可以像使用常规多维数组一样使用语法。

代码语言:javascript
复制
double (*A)[cols] = malloc(sizeof(double[rows][cols]));
...
A[x][y] = ...;

然后,A[x][y]将意味着“在我的数组A中,其中每个项都是一个大小为cols的数组,访问数组号x,然后在该数组中索引y”。

至于如何返回这种类型的数组的问题.不行,因为函数声明必须包含数组指针的维度。它必须是这样的怪物:

代码语言:javascript
复制
double (*create_matrix_2(int rows, int cols))[rows][cols]   // wont compile

如果我们忽略了返回数组指针(和函数指针)的C语法完全是FUBAR,那么上面的C就无效了。因为在编译时必须知道行和cols。

同时解决上述问题的解决方案是通过一个参数返回数组指针:

代码语言:javascript
复制
void create_matrix_2 (int rows, int cols, double(**array)[rows][cols])
{
    // omit inner-most dimension to get sane syntax:
    double (*A)[cols] = malloc(sizeof(double[rows][cols]));

    for (int row = 0; row < rows; row++)
    {
        for (int col = 0; col < cols; col++)
        {
            A[row][col] = row * cols + col;
        }
    }

    for (int row = 0; row < rows; row++)
    {
        for (int col = 0; col < cols; col++)
        {
            printf("%lf, " , A[row][col]);
        }
        printf("\n");
    }

    // "brute" pointer conversion but doesn't break aliasing:
    *array = (void*)A;
}
票数 2
EN

Stack Overflow用户

发布于 2015-05-25 12:45:19

简单的回答是你不能。

问题是,函数返回的类型必须在编译时固定,不能依赖其参数的数值(在运行时提供)。

但是,您可以做的是更改您的create_matrix2()以返回一个空指针。这使用的事实是,在C中,(几乎)任何指针都可以隐式转换为void指针,反之亦然。

代码语言:javascript
复制
   void *create_matrix2(int rows, int columns)
   {
       /* as you've implemented it, except that A should be int not double */
   }

   int main()
   {
        int rows = 2, cols = 3;
        int (*m)[rows][cols] = create_matrix2(rows, cols);

         /*  use *m as a pointer to an array with 2 rows and 3 cols */
   }

然后,它传递你所寻求的东西的幻象

这样做的危险--也是我刚才使用“错觉”一词的原因--是因为与void指针之间的转换阻止编译器进行类型检查。因此,这将通过编译器,但由于从数组的末端掉下而导致未定义的行为。

代码语言:javascript
复制
   int main()
   {
        int rows = 2, cols = 3;
        int (*m)[rows][cols] = create_matrix2(rows-1, cols-1);   /*  whoops - deliberate typos here */

         /*  use *m as a pointer to an array with 2 rows and 3 cols */
   }

因为这实际上告诉编译器将动态分配的数组视为比函数中实际分配的行和列更多的数组。

票数 1
EN

Stack Overflow用户

发布于 2015-05-25 12:33:22

示例

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>

void * create_matrix_2(int rows, int cols){
    int (*A)[rows][cols] = malloc(sizeof(int[rows][cols]));

    for (int row = 0; row < rows; row++){
        for (int col = 0; col < cols; col++){
            (*A)[row][col] = row * cols + col;
        }
    }

    for (int row = 0; row < rows; row++){
        for (int col = 0; col < cols; col++){
            printf("%d, " , (*A)[row][col]);
        }
        printf("\n");
    }
    return A;
}

int main(void){
    int width = 5, height = 3;
    int (*matrix2)[height][width] = create_matrix_2(height, width);

    for (int row = 0; row < height; row++){
        for (int col = 0; col < width; col++){
            printf("%d " , (*matrix2)[row][col]);
        }
        printf("\n");
    }
    free(matrix2);
    return 0;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30438159

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档