我有一个函数concat
来连接矩阵mat1
以形成mat2
。这里 mat1
和 mat2
使用固定尺寸(即 DIM1 = 2、DIM2 = 2、DIM3 = 3、DIM1_1 = 4),但实际上我需要它们具有可变尺寸,所以我将 3d 数组的大小声明为最大大小,如下面的代码中所述(即 DIM2 = 20,DIM3 = 30),但是当我这样做时,程序给出了垃圾值。有人可以建议如何在不使用 malloc() 的情况下使用可变大小的 3d 数组吗?
#include <stdio.h>
#include <string.h>
//!< Dimensions of a 3d array
#define DIM1 2
#define DIM2 2
#define DIM3 3
#define DIM1_1 4
void Concat(int (*mat1)[DIM2][DIM3], int (*mat2)[DIM2][DIM3], int len);
// void Concat(int (*mat1)[20][30], int (*mat2)[20][30], int len);
int main()
{
int mat1[DIM1][DIM2][DIM3] = {{{1,2,3},{4,5,6}},{{1,2,3},{4,5,6}}};
int mat2[DIM1_1][DIM2][DIM3];
Concat(mat1,mat2,2);
return 0;
}
// void Concat(int (*mat1)[20][30], int (*mat2)[20][30], int len){
void Concat(int (*mat1)[DIM2][DIM3], int (*mat2)[DIM2][DIM3], int len){
/*concatenate mat1 to mat2 */
memcpy(mat2[0], mat1, DIM1*DIM2*DIM3 * sizeof mat1);
memcpy(mat2[0+len], mat1, DIM1*DIM2*DIM3 * sizeof mat1);
}
最佳答案
I declared the size of 3d array to max size as commented in my code below (i.e DIM2 = 20, DIM3 = 30) but the program gives garbage value when I do this.
我希望在运行时获取垃圾值之前,编译器会警告您以这种方式创建的类型不匹配。如果没有,那么你可以通过弄清楚如何调高警告级别,或者选择一个更有用的编译器来得到很好的帮助。
无论哪种方式,Concat()
函数的参数都是指向特定维度的二维数组的指针。如果实际参数是指向其他内容的指针,甚至是不同维度的数组,那么结果很差就不足为奇了。事实上,这违反了所谓的“严格别名规则”,因此该行为是未定义的。
Could someone please advise on how to use variable sized 3d arrays without using malloc() ?
我的意思是你想要一个适用于不同维度数组的函数,而不是任何单个数组的维度都会随着时间的推移而变化。您可以执行多种操作,但这里有一些不错的选择:
如果您的实现支持 VLA(在 C99 中是强制的,但自 C11 起是可选的),那么您可以使用它们来支持您的
Concat()
函数。这种事情是我最喜欢的 VLA 用途之一,因为它回避了对其使用的最大实际问题,即可用于自动分配的空间。这种方法可能如下所示:void Concat(size_t dim1, size_t dim2, size_t dim3 int (*source)[dim2][dim3], int (*dest)[dim2][dim3]) { size_t source_size = dim1 * sizeof(*source); memcpy(dest, source, source_size); memcpy(dest + dim1, source, source_size); }
您会注意到,这要求您将源数组的所有维度作为单独的参数传递,并且除了第一个维度之外的所有维度都与两个数组匹配。您可以非常简单地使用它:
int mat1[DIM1][DIM2][DIM3] = /* ... */ int mat2[DIM1 * 2][DIM2][DIM3]; Concat(DIM1, DIM2, DIM3, mat1, mat2);
当然,您可以在同一个程序中使用相同的函数来连接不同维度的数组对,前提是满足已经描述的约束。
如果您不能或不想依赖 VLA,那么您最好的选择可能就是简单地根据这种情况调整上述内容,如下所示:
void Concat(size_t dim1, size_t dim2, size_t dim3, void *source, void *dest) { size_t source_size = dim1 * dim2 * dim3 * sizeof(int); memcpy((char *) dest, source, source_size); memcpy((char *) dest + source_size, source, source_size); }
您可以按照与前一个函数相同的方式调用该函数。
如果您想要更通用,同时提供更简单的函数签名,您可以将上面的内容转换为连接任意对象:
void Concat(size_t source_size, void *source, void *dest) { memcpy((char *) dest, source, source_size); memcpy((char *) dest + source_size, source, source_size); }
这通过让调用者负责计算和传递源对象的大小(以字节为单位)来实现完全的通用性,尽管这不一定是一个大问题。例如,
int mat1[DIM1][DIM2][DIM3] = /* ... */ int mat2[DIM1 * 2][DIM2][DIM3]; Concat(sizeof(mat1), mat1, mat2);
关于c - memcpy() 用于 3D 数组的可变维度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54040807/