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

时间:2016-09-21 22:40:13

标签: c arrays pointers

我想有一个函数,它分配一个2D数组,其中一个维度是固定的,并使用指向数组指针的指针将分配的内存提供给调用者。

例如,function()会返回一个2D图像,其中行size是固定的,但行的number是在函数内确定的。

使用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);
}

我正在使用clanggcc进行编译并获得下一个警告:

clang -o test test.c -g -std=c99
test.c:44:34: warning: incompatible pointer types passing 'unsigned int (**)[size]' to parameter of type 'unsigned int (*)[][*]' [-Wincompatible-pointer-types]
        function (size, &number, &image);
                                 ^~~~~~
test.c:6:63: note: passing argument to parameter 'image' here
    int function (size_t size, size_t *number, int unsigned (*image) [] [size]) {
                                                              ^
1 warning generated.

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

1 个答案:

答案 0 :(得分:-1)

我假设您的要求是:

  • 该函数通过out-parameter“返回”指向VLA的指针。
  • 来电者事先不知道行数;函数决定它并通过out-parameter“返回”它。

代码可能如下所示:

#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;
}

NB。如果您为获取rowcount而不是进行分配,那么它将简化代码。它还会简化代码以返回分配的指针,而不是使用out-parameter。