C 通过引用将2D VLA数组传递给函数,返回分配的内存,无指针数组

C 通过引用将2D VLA数组传递给函数,返回分配的内存,无指针数组,c,arrays,pointers,C,Arrays,Pointers,我想要一个函数,它分配一个二维数组,其中一个维度是固定的,并使用指向数组指针的指针将分配的内存返回给调用者 例如,函数()将返回一个2D图像,其中行的大小是固定的,但行的数量是在函数内部确定的 数组是使用C99 VLA语法定义的,因此我可以在函数内部和外部以普通2D数组image[y][x]的形式访问图像 我认为function()的编写基本正确,但我不知道如何在main(数组声明)中编写代码。在任何情况下,我都无法访问函数外的图像,我会遇到分割错误,编译器会抱怨 我不希望有一个指针数组,应该有

我想要一个函数,它分配一个二维数组,其中一个维度是固定的,并使用指向数组指针的指针将分配的内存返回给调用者

例如,
函数()
将返回一个2D图像,其中行的
大小是固定的,但行的
数量是在函数内部确定的

数组是使用C99 VLA语法定义的,因此我可以在函数内部和外部以普通2D数组
image[y][x]
的形式访问图像

我认为
function()
的编写基本正确,但我不知道如何在main(数组声明)中编写代码。在任何情况下,我都无法访问函数外的图像,我会遇到分割错误,编译器会抱怨

我不希望有一个指针数组,应该有一个
malloc()
free()
并且所有分配的内存都应该是连续的

#include <stdio.h>
#include <stdlib.h>

int function (size_t size, size_t *number, int unsigned (*image) [] [size]);

int function (size_t size, size_t *number, int unsigned (*image) [] [size]) {
    size_t image_size;

    *number = 9;
    image_size = (*number) * size;

    printf ("INSIDE malloc: number=%zu size=%zu image_size=%zu\n", *number, size, image_size); fflush(stdout);
    image = (int unsigned (*) [] [size]) malloc (sizeof(int unsigned) * image_size);

    printf ("INSIDE assign: number=%zu size=%zu\n", *number, size); fflush(stdout);
    for (int unsigned l=0; l<*number; l++) {
        for (int unsigned s=0; s<size; s++) {
            (*image) [l] [s] = (l << 16) + s;
        }
    }
    (*image) [0] [0] = 0xDEADC0DE;

    printf ("INSIDE print: number=%zu size=%zu\n", *number, size); fflush(stdout);
    for (int unsigned l=0; l<*number; l++) {
        printf ("l=%u:", l);
        for (int unsigned s=0; s<size; s++) {
            printf (" %08x", (*image) [l] [s]);
        }
        printf ("\n");
    }

    return (0);
}

int main (int argc, char **argv) {
    size_t size;
    size_t number;

    size = 5;
    int unsigned (* image) [size];

    printf ("TEST:\n"); fflush(stdout);

    function (size, &number, &image);

    fflush(stdout);
//    printf ("OUTSIDE print: number=%zu size=%zu\n", number, size); fflush(stdout);
//    for (int unsigned l=0; l<number; l++) {
//        printf ("l=%u:", l);
//        for (int unsigned s=0; s<size; s++) {
//            printf (" %08x", (*image) [l] [s]);
//        }
//        printf ("\n");
//    }

//    free(image);

    return (0);
}

实际上,我的问题比给定的示例多了一个维度(
list[i][y][x]
),但同样的解决方案应该适用。

我假设您的要求是:

  • 函数通过out参数“返回”指向VLA的指针
  • 调用方事先不知道行数;函数决定它并通过out参数“返回”它
代码可能如下所示:

#include <stdlib.h>

void init(int rows, int cols, unsigned arr[rows][cols])   // same as "unsigned (*arr)[cols]"
{
   for (int r = 0; r < rows; ++r)
        for (int c = 0; c < cols; ++c)
             arr[r][c] = r*c;       
}

void func(int *p_rows, int cols, unsigned (**p_arr)[][cols])
{
   *p_rows = 7;
   *p_arr = malloc( sizeof(unsigned[*p_rows][cols]) );

   if ( !*p_arr )
       exit(EXIT_FAILURE);

   // Possible to initialize here but it makes for more readable code to use a separate function
   // (**p_arr)[2][3] = 5;

   init(*p_rows, cols, **p_arr);
}


int main()
{
   int cols = 7;
   int rows;

   unsigned (*p_arr)[][cols];
   func(&rows, cols, &p_arr);

   // Could do this here instead of calling init() from func()
   init(rows, cols, *p_arr);
   (*p_arr)[2][3] = 5;

   // Optional - allow simpler access syntax
   unsigned (*arr)[cols] = (void *)p_arr;
   init(cols, rows, arr);  
   arr[2][3] = 5;
}
#包括
void init(int rows,int cols,unsigned arr[rows][cols])//与“unsigned(*arr)[cols]相同”
{
对于(int r=0;r


注意。如果使用单独的函数获取行数而不是进行分配,则可以简化代码。它还将简化返回分配指针的代码,而不是使用out参数。

malloc(sizeof(int unsigned)*image\u size)这不是分配2D数组的方法。@Iztok指针的可能重复项不是数组,反之亦然。你认为你传递的指针的类型和它的参数的类型应该不同吗?可能是M的重复。M这是一个很好的答案,它作为广告工作。我仍然不明白为什么双指针指向数组。我认为数组本身是一个指针,所以只需要一个*就可以实现引用。在调试这个问题时,我已经了解到需要括号,因为[]具有优先级,但上面的问题仍然困扰着我。指针远非魔术,但语法仍然让我质疑我的智能。@IztokJeras数组和指针是不同的。数组不是指针。阵列是一个连续存储块。指针是指可以在内存中找到另一个对象的位置。此外,命名数组一旦声明,就不能修改或调整大小。因此,不可能在
main
中声明一个命名数组,然后将某些内容传递给
func
以分配该数组。唯一的选择是动态分配数组,在
main
中有一个命名指针,指向整个数组或数组的第一行(这是我在回答中给出的两种不同情况)。然后,由于
func
需要修改在
main
中声明的指针,因此它必须传递指向该指针的指针。(除非改用返回值)
#include <stdlib.h>

void init(int rows, int cols, unsigned arr[rows][cols])   // same as "unsigned (*arr)[cols]"
{
   for (int r = 0; r < rows; ++r)
        for (int c = 0; c < cols; ++c)
             arr[r][c] = r*c;       
}

void func(int *p_rows, int cols, unsigned (**p_arr)[][cols])
{
   *p_rows = 7;
   *p_arr = malloc( sizeof(unsigned[*p_rows][cols]) );

   if ( !*p_arr )
       exit(EXIT_FAILURE);

   // Possible to initialize here but it makes for more readable code to use a separate function
   // (**p_arr)[2][3] = 5;

   init(*p_rows, cols, **p_arr);
}


int main()
{
   int cols = 7;
   int rows;

   unsigned (*p_arr)[][cols];
   func(&rows, cols, &p_arr);

   // Could do this here instead of calling init() from func()
   init(rows, cols, *p_arr);
   (*p_arr)[2][3] = 5;

   // Optional - allow simpler access syntax
   unsigned (*arr)[cols] = (void *)p_arr;
   init(cols, rows, arr);  
   arr[2][3] = 5;
}