c - memcpy() 用于 3D 数组的可变维度

标签 c

我有一个函数concat来连接矩阵mat1以形成mat2。这里 mat1mat2 使用固定尺寸(即 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/

相关文章:

c - rand() 播种与 time() 问题

C 局部和全局静态变量

c - undefined symbol : PyExc_ImportError when embedding Python in C

c++ - 在这里进行位移有什么意义?

c++ - 将库添加到 C/c++ eclipse indigo 项目

c - 如何将整数四舍五入到最接近的整数倍数?

使用 ICU 将 UCS-2 字符串转换为 UTF-8

c - AT&T 汇编中的算术运算(添加内存和寄存器)

用于生成 FCGI 服务器的 C API?

c - 我该如何处理垃圾?