【问题标题】:Variable dimensional arrays in CC中的可变维数组
【发布时间】:2019-02-11 09:58:54
【问题描述】:

是否可以创建一个可变维数的数组?也就是说,维数将在运行时指定。 如果是,那该怎么做?

请注意,我说的是可变数量的维度,而不是可变长度的数组。

【问题讨论】:

  • malloc 你需要什么,并使用void *void ** 直到你需要别的东西。或者,创建一个一维数组,以及一个将 n 维坐标转换为一维索引的函数。
  • 大多数事情在 C 中都是可能的,但我真的看不出它的用途。听起来您应该使用树或链表等。您要解决的实际问题是什么?
  • 嗯,实际的问题是以尽可能最好的方式(使用最少数量的纸币)为航班(数量可变)的乘客提供零钱,面额的数量和价值是可变的。有一种方法可以在不使用可变维度数组的情况下做到这一点,但我发现这样做会更快、更有效。所以我想知道这是否可能。
  • @Rizwan:这个问题不是那个问题的重复。这个问题询问可变数量的维度。该问题询问的是可变长度的维度。

标签: c multidimensional-array


【解决方案1】:

当然。只需编写您自己的库来处理它:

#include <stdio.h>
#include <limits.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>

struct arrnd_s {
    void *memory;
    size_t membsize;
    size_t *dims;
    size_t dimcnt;
};

static inline size_t _arrnd_arraysize(struct arrnd_s *t)
{
    size_t ret = 1;
    for (size_t i = 0; i < t->dimcnt; ++i) {
        ret *= t->dims[i];
    }
    return ret;
}

struct arrnd_s *arrnd_new(size_t membsize, size_t dimcnt, ...)
{
    struct arrnd_s *t = malloc(sizeof(*t));
    if (t == NULL) {
        goto T_MALLOC_ERR;
    }
    t->dims = malloc(dimcnt * sizeof(*t->dims));
    if (t->dims == NULL) {
        goto T_DIMS_ERR;
    }

    va_list va;
    va_start(va, dimcnt);
    for (size_t i = 0; i < dimcnt; ++i) {
        t->dims[i] = va_arg(va, size_t);
    }
    va_end(va);

    t->dimcnt = dimcnt;
    t->memory = malloc(_arrnd_arraysize(t) * membsize);
    if (t->memory == NULL) {
        goto T_MEMORY_ERR;
    }
    t->membsize = membsize;

    return t;

    T_MEMORY_ERR:
    free(t->dims);
    T_DIMS_ERR:
    free(t);
    T_MALLOC_ERR:
    return NULL;
}

void arrnd_free(const struct arrnd_s *t)
{
    assert(t != NULL);
    free(t->memory);
    free(t->dims);
    free((void*)t);
}

size_t arrnd_arraysize(struct arrnd_s *t)
{
    assert(t != NULL);
    assert(t->dims != NULL);
    assert(t->dimcnt >= 1);
    return _arrnd_arraysize(t);
}

size_t arrnd_getdim(struct arrnd_s *t, size_t dimpos)
{
    assert(t != NULL);
    assert(t->dims != NULL);
    assert(t->dimcnt >= 1);
    assert(dimpos < t->dimcnt);
    return t->dims[dimpos];
}

void *arrnd_getpnt_v(struct arrnd_s *t, va_list va)
{
    assert(t != NULL);
    assert(t->dims != NULL);
    assert(t->dimcnt >= 1);
    size_t pos = 0;
    for (size_t i = 0; i < t->dimcnt; ++i) {
        const size_t dim = va_arg(va, size_t);
        pos += dim;
        if (i != t->dimcnt - 1) {
            pos *= t->dims[i];
        }
    }
    return &((char*)t->memory)[pos * t->membsize];
}

void *arrnd_getpnt(struct arrnd_s *t, ...)
{
    va_list va;
    va_start(va, t);
    void * const ret = arrnd_getpnt_v(t, va);
    va_end(va);
    return ret;
}

int main() 
{

    struct arrnd_s *arrnd = arrnd_new(sizeof(int), 4, 2, 4, 4, 8);
    assert(arrnd != NULL);
    assert(arrnd_arraysize(arrnd) == 2 * 4 * 4 * 8);


    for (size_t i = 0; i < arrnd_getdim(arrnd, 0); ++i) {
        for (size_t j = 0; j < arrnd_getdim(arrnd, 1); ++j) {
            for (size_t k = 0; k < arrnd_getdim(arrnd, 2); ++k) {
                for (size_t l = 0; l < arrnd_getdim(arrnd, 3); ++l) {
                    *(int*)arrnd_getpnt(arrnd, i, j, k, l) = i + j + k + l;
                }
            }
        }
    }

    for (size_t i = 0; i < arrnd_getdim(arrnd, 0); ++i) {
        for (size_t j = 0; j < arrnd_getdim(arrnd, 1); ++j) {
            for (size_t k = 0; k < arrnd_getdim(arrnd, 2); ++k) {
                for (size_t l = 0; l < arrnd_getdim(arrnd, 3); ++l) {
                    printf("[%zu][%zu][%zu][%zu] = %d\n", i, j, k, l, *(int*)arrnd_getpnt(arrnd, i, j, k, l));
                }
            }
        }
    }

    arrnd_free(arrnd);

    return 0;
}

顺便说一句,以下是我一直认为在 C 中很酷的东西,但这是编译时,而不是运行时:

int main() {
    int memory[256];
    for (size_t i = 0; i < sizeof(memory)/sizeof(*memory); ++i) {
        memory[i] = i;
    }


    int *arr1d = (void*)memory;
    printf("1d[%d] = %d == %d\n", 1, arr1d[1], memory[1]);

    int (*arr2d)[16] = (void*)memory;
    printf("2d[%d][%d] = %d == %d\n", 2, 2, arr2d[2][2], memory[2 * 16 + 2]);

    int (*arr3d)[8][8] = (void*)memory;
    printf("3d[%d][%d][%d] = %d == %d\n", 2, 2, 2, arr3d[2][2][2], memory[(2 * 8 + 2) * 8 + 2]);

    int (*arr4d)[4][4][4] = (void*)memory;
    printf("4d[%d][%d][%d][%d] = %d == %d\n", 2, 2, 2, 2, arr4d[2][2][2][2], memory[((2 * 4 + 2) * 4 + 2) * 4 + 2]);

    int (*arr5d)[2][2][2][2] = (void*)memory;
    printf("5d[%d][%d][%d][%d][%d] = %d == %d\n", 1, 1, 1, 1, 1, arr5d[1][1][1][1][1], memory[(((1 * 2 + 1) * 2 + 1) * 2 + 1) * 2 + 1]);

    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    相关资源
    最近更新 更多