超出范围的多维数组声明

时间:2018-04-19 18:38:52

标签: c arrays multidimensional-array declaration

这个问题是参考此处提供的解决方案/解释Allocating variable length multi dimensional arrays(参见接受的答案)。

在我的情况下,我使用相同的功能来定义3D数组,如下面的

void arr_alloc (int x, int y, int z, int(**aptr)[x][y][z])
{
  *aptr = malloc( sizeof(int[x][y][z]) ); // allocate a true 3D array
  assert(*aptr != NULL);
} 

对于我正在处理的代码库,这是一个巨大的项目存储库,早些时候我使用的指针指向指向类型(***数组)的指针,然后交错使我可以将它用作3D(伪)阵列。为此,我曾将变量声明为extern int ***array,并将指针定义在单独的头文件中int ***array。我的问题 - (a)对于新的函数,应该是数组的声明和定义,因为SO参考答案使用了声明和定义,例如

int x = 2;
int y = 3;
int (*aptr)[x][y];

(b)使用size_t vs int作为索引变量的激励,假设size_t占用8个字节,而int占用4个字节。

PS。我在gdb中检查了上面提到的声明和定义行之后的变量类型(也在SO答案中)(int (*)[variable length][variable length][variable length]) 0x0

编辑:请注意,这个问题是关于数组/数组指针的声明和定义,而不是分配和设置数组的函数的声明。

1 个答案:

答案 0 :(得分:2)

函数声明对于分配3D数组是正确的。指向这样一个数组的指针将具有类型int (*)[a][b][c],因此该函数需要接受该类型的指针的地址以写入它,即int (**)[a][b][c],这就是你所拥有的。

要使用此功能,您需要按如下方式调用它:

int s1=2, s2=3, s3=4;
int (*p)[s1][s2][s3];
arr_alloc(s1,s2,s3,&p);

然后你可以像这样写入3D数组:

int i,j,k;
int n = 0;
int i,j,k;
int n = 0;
for (i=0;i<s1;i++) {
    for (j=0;j<s2;j++) {
        for (k=0;k<s3;k++) {
            (*p)[i][j][k] = n++;
        }
    }
}

编辑:

真正的多维数组必须声明除第一个维度之外的所有维度的大小。如果您的数组是在文件范围声明的,那意味着这些维度的大小必须是编译时常量。

如果尺寸必须变化,则需要将其设为void *并根据需要进行投射。你在这里放松了一些类型检查,但这是唯一的方法:

int s1, s2, s3;
void *arr;

void arr_alloc (int x, int y, int z)
{
  int (*p)[x][y][z] = malloc( sizeof(int[x][y][z]) );
  assert(p != NULL);
  arr = p;
  s1=x;
  s2=y;
  s3=z;
}

int main()
{
    arr_alloc(2,3,4);
    int (*p)[s1][s2][s3] = (int(*)[s1][s2][s3])arr;

    int i,j,k;
    int n = 0;
    for (i=0;i<s1;i++) {
        for (j=0;j<s2;j++) {
            for (k=0;k<s3;k++) {
                    (*p)[i][j][k] = n++;
            }
        }
    }
    for (i=0;i<s1;i++) {
        for (j=0;j<s2;j++) {
            for (k=0;k<s3;k++) {
                    printf("%d:%d:%d=%d\n",i,j,k,(*p)[i][j][k]);
            }
        }
    }
    free(p);
    return 0;
}