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