【问题标题】:Out of scope declaration of a multidimensional array多维数组的超出范围声明
【发布时间】:2018-04-19 18:38:51
【问题描述】:

此问题参考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 占用 8 个字节而 int 占用 4 个字节,使用 size_tint 作为索引变量的激励。

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

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

【问题讨论】:

  • 我相信 for(a),因为数组会衰减为 C 中的指针:void arr_alloc(int x, int y, int ***aptr); 会起作用。我不太确定你在问什么(b)。也就是说,有时有人向我指出,很少需要成为 3 星程序员。
  • 这段代码的一切都很疯狂,包括assert
  • @ryyker 我想我已经编辑过让自己清楚。问题是关于变量声明而不是函数声明
  • @ryyker 数组只衰减一维。二维数组衰减为指向外部数组的一维数组元素的指针。一旦完成,它已经是一个指针,而不是一个数组值,并且不需要进一步衰减。
  • @melpomene 好吧,我有点适应了一个写得很好的和被接受的答案。事实上,人们有不同的编码风格/方式。如果你可以评论“你发现什么特别疯狂”,那么这将有助于我修改实现。

标签: c arrays multidimensional-array declaration


【解决方案1】:

函数声明对于分配 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;
}

【讨论】:

  • 我在一个小的测试代码中也是如此。在实际情况下,我想将变量p or *p or *p[ ][ ][ ] 声明为extern ....。我指的是这个。在我的情况下如何声明变量。
  • 真正的多维数组必须声明除第一个以外的所有维度的大小。如果您的数组是在文件范围内声明的,则意味着这些维度的大小必须是编译时常量。如果它们必须变化,那么您就会陷入交错数组。
  • @datapanda Actully,如果你使用void *,你可以逃脱它。查看我的编辑。
猜你喜欢
  • 2018-08-04
  • 2020-04-02
  • 2018-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-04
  • 1970-01-01
相关资源
最近更新 更多