4

我必须使用三重指针将内存分配给 3D 数组。

#include <stdio.h>
int main()
{
    int m=10,n=20,p=30;
    char ***z;
    z = (char***) malloc(sizeof(char**)*m*n*p);
    return 0;
}

这是正确的做法吗?(我认为我所做的是不正确的。)

4

5 回答 5

6

要完全分配 3D 动态数组,您需要执行以下操作:

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

int main()
{
    int m=10,n=20,p=30;
    char ***z;

    z = malloc(m * sizeof(char **));
    assert(z != NULL);
    for (i = 0; i < m; ++i)
    {
        z[i] = malloc(n * sizeof(char *));
        assert(z[i] != NULL);
        for (j = 0; j < n; ++j)
        {
            z[i][j] = malloc(p);
            assert(z[i][j] != NULL);
        }
    }
    return 0;
}

释放数据留给读者作为练习。

于 2012-05-28T09:03:42.017 回答
4

无需malloc()在 C 中强制转换 , 的返回值。

如果您希望m * n * p直接存储字符(并自己计算地址),那么您当然不应该按 a 的大小来缩放分配 char **

你的意思是:

int m = 10, n = 20, p = 30;
char *z = malloc(m * n * p * sizeof *z);

这将分配 10 * 20 * 30 = 6000 字节。这可以看作是形成一个高度的立方体,p沿垂直轴的每个“切片”都是n * m字节。

由于这是用于手动寻址,因此您不能使用 egz[k][j][i]来索引,而必须使用z[k * n * m + j * m + i].

于 2012-05-28T09:04:51.877 回答
2

如果您不需要在单个连续块中分配内存(IME 是通常的情况),您可以执行以下操作:

char ***z;
z = malloc(sizeof *z * m); // allocate m elements of char **
if (z)
{
  int i;
  for (i = 0; i < m; i++)
  {
    z[i] = malloc(sizeof *z[i] * n); // for each z[i], 
    if (z[i])                        // allocate n elements char *
    {
      int j;
      for (j = 0; j < n;j++)
      {
        z[i][j] = malloc(sizeof *z[i][j] * p); // for each z[i][j], 
        if (z[i][j])                           // allocate p elements of char
        {
           // initialize each of z[i][j][k]
        }
      }
    }
  }
}

请注意,您需要以相反的顺序释放此内存:

for (i = 0; i < m; i++)
{
  for (j = 0; j < n; j++)
    free(z[i][j];
  free(z[i]);
}
free(z);

如果您确实需要将内存分配到一个连续的块中,那么您有几个选择。您可以分配一个块并手动计算偏移量:

char *z = malloc(sizeof *z * m * n * p); // note type of z!
...
z[i * m + j * n + k] = some_value();

当你完成后,你只需要做一个free

free(z);

如果您有支持可变长度数组的 C99 编译器或 C11 编译器,则可以执行以下操作:

int m=..., n=..., p=...;
char (*z)[n][p] = malloc(sizeof *z * m);

这声明z为指向nxp数组的指针char,我们分配m这样的元素。内存是连续分配的您可以使用普通的 3-d 数组索引语法 ( z[i][j][k])。像上面的方法一样,你只需要一个free调用:

free(z);

如果您没有支持 VLA 的 C99 编译器或 C11 编译器,则需要 makenp编译时常量,例如

#define n 20
#define p 30

否则最后一种方法是行不通的。

编辑

m在这种情况下,不需要是编译时常量,只需nand p

于 2012-05-28T11:58:59.780 回答
0

您将需要以下嵌套循环 -

z = (char**)malloc(sizeof(char*) * m);
for (int i = 0; i < m; ++i)
{
    *(z + i) = (char*)malloc(sizeof(char*) * n);
    for (int j = 0; j < n; ++j)
    {
        *(*(z + i)) = (char)malloc(p);
    }
}

可能在语法上不准确,但应该是这样的。

于 2012-05-28T09:04:14.930 回答
0

sizeof(char)不想要sizeof(char**),因为后者会给你一个指针的大小,在大多数现代系统上它将是 4 个字节,而不是你期望的 1 个字节。

于 2012-05-28T09:05:01.687 回答