堆上的动态多维数组

框架

我想创建一个函数,该函数只需调用malloc就可以在堆上分配多维数组。(指针数组)因此函数调用将如下所示:

size_t dim[2]  = {2, 4};
int **_2darray = alloc_array(sizeof(int), dim, 2);
// ^ should be the "same" as:
int __2darray[2][4];

到目前为止,我所要做的是保存数组和指针所需的整个块的SIZE计算:

void *alloc_array(size_t element_size, size_t dimensions[static 1], size_t ndims)
{
    unsigned char *DATA = NULL;
    size_t SIZE         = 0;
    size_t multiplicators[ndims];

    // Calculate for each dimension the multiplier 
    // SIZE 3d array:  (N1 * sizeof(T **) + (N1 * N2 + sizeof(T *) + (N1 * N2 * n3 + sizeof(T))
    //                  ^- first mulitplier ^ second multiplier      ^ third multiplier

    for (size_t i = 0;  i < ndims; ++i) {
        multiplicators[i] = dimensions[i];

        for (size_t j = 0; j < i; ++j) {
            multiplicators[i] *= dimensions[j];
        }
    }

    SIZE = 0;
    for (size_t dimI = 0; dimI < ndims; ++dimI) {
        size_t mulval = multiplicators[dimI];

        // The elements are in the "last" dimension
        if (dimI+1 == ndims) {
            SIZE += element_size * mulval;
        } else {
            // All other elements are pointers to the specific element
            SIZE += sizeof(void *) * mulval;
        }
    }

    DATA = malloc(SIZE);
    return DATA;
}

因此,现在SIZE计算即可。但是现在,我不得不将指针设置为正确的元素。我知道处理静态尺寸很容易,但是我希望使用动态尺寸来完成。

代词
#include <stdlib.h>
#include <stdio.h>

void fill_array_pointers (void** pointers, char* elements, 
                  size_t element_size, size_t total_elements_size, 
                  size_t dimensions[], size_t ndims)
{
    if (ndims == 2)
    {
        size_t i;
        for (i = 0; i < dimensions[0]; ++i)
        {
            pointers[i] = elements + i * element_size * dimensions[1];
        }
    }
    else
    {
        size_t i;
        size_t block_size = total_elements_size / dimensions[0];
        for (i = 0; i < dimensions[0]; ++i)
        {
            pointers[i] = pointers + dimensions[0] + i * dimensions[1];
            fill_array_pointers (pointers + dimensions[0] 
                                          + i * dimensions[1], 
                                  elements + block_size * i, 
                                  element_size, block_size, 
                                  dimensions+1, ndims-1);
        }
    }
}

void* alloc_array (size_t element_size, size_t dimensions[], 
                    size_t ndims)
{
    size_t total_elements_size = element_size;
    int i;

    // total size of elements

    for (i = 0; i < ndims; ++i)
        total_elements_size *= dimensions[i];

    // total size of pointers

    size_t total_pointers_size = 0;
    int mulval = 1;
    for (i = 0; i < ndims-1; ++i)
    {
        total_pointers_size += dimensions[i] * sizeof(void*) * mulval;
        mulval *= dimensions[i];
    }

    size_t total_size = total_pointers_size;
    size_t oddball = total_pointers_size % element_size; 
                // really needs to be alignof but we don't have it
    if (oddball) total_size += (element_size - oddball);
    total_size += total_elements_size;

    void* block = malloc (total_size);
    void** pointers = block;
    char* elements = (char*)block + total_size - total_elements_size;

    fill_array_pointers (pointers, elements, element_size,
                         total_elements_size, dimensions, ndims);
    return block;
}

试驾:

int main ()
{
    size_t dims[] = { 2, 3, 4 };
    int*** arr = alloc_array(sizeof(int), dims, 3);


    int i, j, k;
    for (i = 0; i < dims[0]; ++i)
        for (j = 0; j < dims[1]; ++j)
            for (k = 0; k < dims[2]; ++k)
            {
                arr[i][j][k] = i*100+j*10+k;
            }

    for (i = 0; i < dims[0]*dims[1]*dims[2]; ++i)
    {
        printf ("%03d ", (&arr[0][0][0])[i]);
    }
    printf ("\n");

    free (arr);
}

对于以下情况下的多维char数组,这将不起作用sizeof(char*) != sizeof(char**)这样的系统存在但很少见。多维char数组毫无意义。

该测试在的条件下可以正常运行valgrind

这比其他任何事情都更明智。如果需要最高性能,请不要使用指针数组,而应使用平面数组和难看但有效的显式索引计算。如果您需要清晰简洁的代码,最好将每个级别分别分配。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章