【问题标题】:multi-dimension array allocation with calloc使用 calloc 的多维数组分配
【发布时间】:2017-06-23 12:12:22
【问题描述】:

我有以下二维数组 N*2(我不能修改它的声明):

bool* myArray[2];
int N;

我想用 calloc 分配它但没有成功:

myArray = calloc(N, 2*sizeof(bool));
for (int i=0; i!=N; i++)
{
    myArray[i] = calloc(2, sizeof(bool));
}

编译器提升了我(在第一个 calloc 上):

error: incompatible types in assignment of 'void*' to 'bool* [2]'

我做错了什么?

【问题讨论】:

  • myArray = calloc(N, 2*sizeof(bool)); -> myArray = calloc(N, 2*sizeof(bool*));
  • 你的数组已经有 2 个 bool*,你不需要 myArray = calloc(N, 2*sizeof(bool));
  • bool* myArray[2];
  • calloc() 返回一个 void 指针,您将其分配给 bool 指针。
  • @GauravPathak 这是在 C 中正确的做法。

标签: c arrays memory-management compiler-errors calloc


【解决方案1】:

这段代码:

bool* myArray[2];
int N;

不声明一个二维数组,而是一个指针数组。这是一个重要的区别,因为二维数组不是指向数组的指针数组——它们只是连续存储,就像一维数组一样(一个“行”接一个)。 p>

因此,正如您所说,您不能更改声明,让我们来解释一下指针数组需要什么。通过您的声明,您正好声明了 2 个指针,因此 N 只能表示“第二维”,如这些指针指向的数组中的元素数。使用此声明,您可以拥有 2 次 N 布尔数组。分配它们看起来像这样:

myArray[0] = calloc(N, sizeof(bool));
myArray[1] = calloc(N, sizeof(bool));

myArray 本身无需分配空间,通过您的声明,它已经具有自动存储功能。

【讨论】:

  • 当你写“二维数组不是数组数组”时,你的意思是“二维数组不是指针数组 “?这样似乎更有意义。
  • @IanAbbott 我写了更抽象的 arrays of arrays 因为在某些语言中,多维数组是这样定义的。但是当然,要在 C 中构建 arrays of arrays,您必须使用指针。
  • 我认为您试图区分数组和锯齿状数组,但是“二维数组不是数组的数组”并不完全正确。给定char arr[2][2];arrchar 的两个数组组成的数组。连续存储,是的,但请注意,在大多数表达式中,arr 将衰减为指向其第一个元素的指针,chars 的数组:(*)[2]
  • @DavidBowling 好的,这是一个有效的反对意见(这里给出了arr 的“指针类型”)。我不确定锯齿状数组这个术语是否能说明问题,也许我会使用简单的数组指针数组。 (解释 C 中的指针和数组很难,这可能是很多初学者弄错的原因)
  • 同意。似乎需要记住几部分才能理解指针和数组,这意味着初学者必须先消化一下。是的,我认为 数组指针数组 很好,并且比 锯齿状数组 不太可能引起初学者的混淆。
【解决方案2】:

改为这样做:

bool (*myArray)[2] = calloc(N, sizeof(*myArray));

或者,如果您不想修改您的声明,只需去掉这里的第一个 calloc 并修改您的 for 循环:

myArray = calloc(N, 2*sizeof(bool)); // you do not need that
for (int i=0; i < 2; i++)
{
    myArray[i] = calloc(N, sizeof(bool));
}

PS:在 C 中,我们 don't cast malloc,当我们希望编译 C++ 时,我们会这样做。

【讨论】:

  • 我无法更改标题中 myArray 的声明
  • 问题说明“(我无法修改其声明)”。因此,无论出于何种原因,答案都应该说明这不是二维数组,而是指向数组的指针数组......并说明它是如何正确完成的。
  • 一个更简单的解决方案是去掉第一行:myArray = calloc(N, 2*sizeof(bool));
  • @Coldspeed 确实如此,但我想,在这种情况下,单班轮看起来更漂亮。
  • @rudy 如果您需要演员表,您使用的是c++ 编译器。这不是编译 C 代码的好主意。
【解决方案3】:

不能重新分配myArray 的原因是myArray 不是指针。它是一个由两个指向bool 的指针组成的数组。与您的描述相反,它也不是“二维数组”。

你需要做的就是

for (int i=0; i < 2; ++i)
{
    myArray[i] = calloc(N, sizeof(bool));
}

然后您可以将其用作“2*N”数组,例如将所有元素设置为true

for (int i = 0; i < 2; ++i)
{
    for (j = 0; j < N; ++j)
          myArray[i][j] = true;
}

如果您交换索引的顺序(例如,在上面的内部循环中使用 myArray[j][i])并将 myArray 用作“N*2”数组而不是“2*N”数组,结果将是未定义的行为。如果不更改 myArray 的声明,就没有解决方案来改变它——你说过你不想这样做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-18
    • 2011-10-01
    • 1970-01-01
    • 2012-08-10
    • 1970-01-01
    • 2013-02-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多