如何在C语言中声明一个大小可变的二维数组?

13

我有一个项目的问题。我需要创建一个变量大小的二维数组来存储一些预测误差...这与图像有关。问题是我需要加载不同尺寸的图像,因此对于每个图像,我都需要从文件中获取相应数量像素的二维数组..我已经搜索了你们的问题,但这不是我想要的。有人可以帮帮我吗?

谢谢

3个回答

11

如果您在函数作用域内有一款现代C编译器(至少是 C99),那么实现起来就非常简单:

unsigned arr[n][m];

这被称为可变长度数组(VLA)。如果数组太大,可能会出现问题。因此,如果您有大型图像,可以执行以下操作:

unsigned (*arr)[m] = malloc(sizeof(unsigned[n][m]));

之后

free(arr);

请记住,上面提到的可变长度数组将在堆栈上分配。第二个与问题不太相关的事情是,C++ 0X不支持此功能(但由于这是一个C问题,所以可以正常工作)。 - Yavar
@Yavar,这就是为什么我也提到了使用malloc分配的版本。即使如此,它仍然是“可变修改类型”。而且C++显然有其他方法来处理多维数组,所以是的,这完全不相关。 - Jens Gustedt

4

如果您需要内存是连续的,您有几个选择。

您可以动态分配单个内存块,然后手动计算偏移量,例如:

size_t rows, cols;
...
int *arr = malloc(sizeof *arr * rows * cols);
...
arr[i * rows + j] = ...; // logically equivalent to arr[i][j]

你可以设置第二个指针数组指向主数组:
int **arrp = malloc(sizeof *arrp * rows);
...
for (i = 0; i < rows; i++)
  arrp[i] = &arr[i * rows];
...
arrp[i][j] = ...;

请记住,您需要释放两个arrarrp

如果您有C99实现,可以像下面这样设置指向VLA的指针:

int (*arrp)[cols] = (int (*)[cols]) arr;
...
arrp[i][j] = ...;

请注意,在这种情况下,您不需要为次级数组分配任何内存,也不需要手动计算指向主数组的指针;您只需要将 arrp 设置为与 arr 相同的位置,并让指针算术规则完成所有工作。
如果图像不是太大,您可以设置一个VLA(再次,C99或更高版本):
int arr[rows][cols];

但实际上这并不是一个好主意;堆栈帧的大小通常非常有限。


在您的第三种情况中,我认为分配最好按照我在答案中给出的方式进行。直接使用malloc,无需转换,这只会使代码更加晦涩难懂。 - Jens Gustedt

0
你需要动态分配内存。使用双指针逻辑。
例如:
int n=10; <<-u can change this.
int **a;
a=(int **)malloc(sizeof(*int)*n);
for (int i=0;i<n;i++){
 a[i]=(int *)malloc(sizeof(int)*n);// or *(a+i)
}

当然不是,但你可以让它表现得像一个数组。 - Akshaya Shanbhogue
这就是本地C的限制。动态数组创建或者内存分配总体来说是C的一个主要缺陷,这也导致了人们的离开。但它仍然是一种很好的语言,因为它提供了原始的力量。这个例子证明了你可以进行低级别的操作来实现所需的结果。 - Akshaya Shanbhogue
1
但是你仍然没有回答我的问题。C语言具有动态分配的多维数组。为什么你要模拟一种语言本来就提供的功能呢? - Jens Gustedt
1
很抱歉,您是错的。我不了解C99标准,但旧版本如K&RC(原始版本)不支持像“int a [m] [n];”这样的东西<<- m和n必须在编译时知道。 - Akshaya Shanbhogue
此外,如果它确实支持,那么询问这个问题的意义是什么? - Akshaya Shanbhogue
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接