如何访问具有多个括号的一维数组以提高可读性?

Sai*_*iph 9 c c++ multidimensional-array square-bracket c-preprocessor

我有一个巨大的代码使用由指针管理的3D数组.就像是:

int *** tab;
tab = malloc(m*sizeof(int**));
for(i= 1..n) tab[i] = malloc(n*sizeof(int*));  
... etc...
Run Code Online (Sandbox Code Playgroud)

然后使用以下方法访问元素:

tab[i][j][k] = ...
Run Code Online (Sandbox Code Playgroud)

但由于此结构的特定问题,我想将tab声明为连续数组,但仍然在代码中使用带有3个括号的语法.编译器将在内部替换它们,如下所示:

tab[i][j][k] = ...  =>  tab[i*m*n+j*m+k] = ...
Run Code Online (Sandbox Code Playgroud)

因此只使用一个指针解引用访问该数组.我不想更改源代码(没有sed).

例如,我可以通过在堆栈中声明制表符来完成此操作:

int tab[n][m][l];
Run Code Online (Sandbox Code Playgroud)

但不幸的是,如果m并且n是运行时变量,这不起作用.

Ser*_*sta 5

C++的方法是将3D数组封装在一个类中以拥有一个自然的访问器:

struct Arr3D
{
    int *arr;
    const int n, m, p; //size of the tab in 3 dimensions

public:
    Arr3D(int n, int m, int l): n(n), m(m), p(l) {
        arr = new int[n * m * p];
    }

    ~Arr3D() {
        delete[] arr;
    }

    int& val(int i, int j, int k) {   // read-write accessor
        // optionaly test for 0<=i<n...
        return arr[k + p * (j + i * m)];
    }
};
Run Code Online (Sandbox Code Playgroud)

您只需使用以下命令创建和使用数组:

Arr3D * parr = new Arr3D(3,4,5); // dynamic allocation
Arr3D arr(3, 4, 5);              // automatic allocation
...
arr(1,2,3) = 5;
int i = arr(2,0,1);
Run Code Online (Sandbox Code Playgroud)

或者,如果您想tab[i][j][k]使用能够在2D数组上提供视图的辅助Arr2D类,您可以保留语法:

struct Arr2D
{
    int *arr;
    const int n, m; //size of the tab in 2 dimensions
    const bool is_view;

public:
    Arr2D(int n, int m): n(n), m(m), is_view(false) {
        arr = new int[n * m];
    }
    Arr2D(int *arr, int n, int m): arr(arr), n(n), m(m), is_view(true) {}

    ~Arr2D() {
        if (! is_view) delete[] arr;
    }

    int * operator[] (int i) {
        return arr + i * m;
    }
};

struct Arr3D
{
    int *arr;
    const int n, m, p; //size of the tab in 3 dimensions

public:
    Arr3D(int n, int m, int l): n(n), m(m), p(l) {
        arr = new int[n * m * p];
    }

    ~Arr3D() {
        delete[] arr;
    }

    Arr2D operator[](int i) {
        return Arr2D(arr + i * p * m, m, p);
    }
};
Run Code Online (Sandbox Code Playgroud)

你现在可以简单地使用arr[i][j][k]......


Ian*_*ott 2

在 C(C99 或 C11)中,tab可变维度的数组可以作为函数参数传递,只要其维度也在前面的参数中传递即可。这是一个例子来说明我的意思:

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

int sum3d(unsigned int dim_n, unsigned int dim_m, unsigned int dim_l,
          int tab[dim_n][dim_m][dim_l])
{
    int total = 0;
    int n, m, l;

    for (n = 0; n < dim_n; n++)
    {
        for (m = 0; m < dim_m; m++)
        {
            for (l = 0; l < dim_l; l++)
            {
                total += tab[n][m][l];
            }
        }
    }
    return total;
}

int main(void)
{
    unsigned int dim_n, dim_m, dim_l;
    unsigned int n, m, l;
    int tot;

    dim_n = 10;
    dim_m = 5;
    dim_l = 4;

    int (*tab)[dim_m][dim_l] = calloc(dim_n, sizeof(*tab));
    if (!tab)
    {
        fprintf(stderr, "Memory allocation failure!\n");
        exit(1);
    }
    for (n = 0; n < dim_n; n++)
    {
        for (m = 0; m < dim_m; m++)
        {
            for (l = 0; l < dim_l; l++)
            {
                tab[n][m][l] = 1;
            }
        }
    }

    printf("total = %d\n", sum3d(dim_n, dim_m, dim_l, tab));
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在 function 中sum3dtab可以声明为int tab[][dim_m][dim_l]或 as int (*tab)[dim_m][dim_l],在这两种情况下都省略最左边的维度。