【问题标题】:How to malloc a 2d jagged array using a pointer passed by reference to a function in C如何使用通过引用传递给 C 中的函数的指针来分配 2d 锯齿状数组
【发布时间】:2012-10-09 03:26:21
【问题描述】:

我在main() 块中声明了一个二维锯齿状数组。这将被传递给函数以分配内存。以下是最精简的情况,它编译但在运行时崩溃。我哪里错了?

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

void alloc2d(double ***p);


int main () {

    double **data;

    alloc2d(&data);
    printf("Before assign to data\n");
    data[0][0] = 0.1;
    printf("After assign to data\n");
    free(data);
}


void alloc2d(double ***p) {

    int i, n, m;

    // Get some dynamically assigned sizes
    printf("Enter size: ");
    scanf("%d %d", &n, &m);    
    // Now allocate
    *p = malloc(n * sizeof(double*));
    for (i = 0; i < n; i++) {
        *p[i] = malloc(m * sizeof(double));
    }
    printf("End of alloc2d\n");
}

这会读取值,但当我输入低数字(即“1 1”)时会崩溃,但当我输入高数字(即“10 10”)时会崩溃。

【问题讨论】:

    标签: c function malloc multidimensional-array


    【解决方案1】:

    你犯了一个非常简单的语法错误

    *p[i] = (double*)malloc(m * sizeof(double));
    

    应该是

    (*p)[i] = (double*)malloc(m * sizeof(double));
    

    这是因为在 C 中,[] 运算符的优先级高于 *。 所以当你输入*p[i]时, 它被翻译成**(p + i)

    这意味着:您要求编译器通过将 p 的地址偏移i * sizeof(double**) 来计算地址,这显然不是您真正想要的。

    所以,为了强制编译器首先取消对 p 的引用,只需用括号括住 *p

    【讨论】:

    • 非常感谢!这与运算符优先级有关吗?即在解析索引后取消引用指针?
    • @Bredan,是的。 :) Here 是一个非常方便的运算符优先级图表。
    • 您的翻译中缺少*p[i] 已经转换为 *(p+i),所以 *p[i] 变为 **(p+i)。另一方面,偏移量将是i*sizeof(double**) 字节,所以你的一颗星星掉了几行。
    • 嗯,我不确定我是否明白你的意思。据我了解,p 的类型为double***,因此p[i] 的类型应为double**。然后,(*p)[i],即**(p + i),将引用duoble*。这应该是正确的,因为 OP 正试图为其分配一个双精度数组......我在这里遗漏了什么吗?
    • @BeyondSora 不,(*p)[i] 将是 *(*p + i)。对于允许类型(和值,以便定义行为)的任何两个表达式,e1[e2] 等价于*(e1 + e2)。所以*p[i] 变成*(p[i]) = *(*(p+i)) - 外括号可以省略 - 你写了“所以当你输入*p[i] 时,它被翻译成*(p + i)”,那里少了一个星号。
    【解决方案2】:

    运算符优先级就是答案。 *p[i] 等价于 *(p[i])。这使您可以访问位于 data 指针之后的内存,这会破坏堆栈上的其他一些变量,或者完全崩溃。

    您正在寻找(*p)[i],它将是新分配数组中的第 i 个条目。

    【讨论】:

      【解决方案3】:

      你的 alloc2d() 分配的并不是真正的二维数组,而是:

      • 1 个 1D n 长指针数组,指向 double
      • n 个 1D m 长的双精度数组

      只有在编译时知道除了最后一个维度之外的所有维度时,C 中的多维数组才是可能的:

      double a[5][11];
      

      也许,这个程序可以帮助你理解......注意,COLUMNS 是一个编译时常量,即使 rows 是一个运行时变量:

      #include <stdio.h>
      #include <stdlib.h>
      #include <sysexits.h>
      #include <err.h>
      
      typedef double  myrow_t[11]; /* 11 columns */
      #define COLUMNS (sizeof(myrow_t)/sizeof(double))
      
      static unsigned
      alloc2d(myrow_t **pd)
      {
      unsigned int rows;
      
      printf("Enter the number of rows: ");
      while (scanf("%u", &rows) != 1)
          printf("\ninvalid input, please, try again: ");
      
      *pd = malloc(rows * sizeof(**pd));
      if (*pd == NULL)
          err(EX_TEMPFAIL, "Out of memory");
      
      return rows;
      }
      
      int
      main()
      {
      myrow_t     *d;
      unsigned int     row, column, rows;
      
      rows = alloc2d(&d);
      
      for (row = 0; row < rows; row++)
          for (column = 0; column < COLUMNS; column++)
              d[row][column] = row * column;
      
      for (row = 0; row < rows; row++) {
          printf("Row %3d:\t", row);
          for (column = 0; column < COLUMNS; column++)
              printf("%.0f\t", d[row][column]);
          puts("");
      }
      
      free(d);
      return 0;
      }
      

      【讨论】:

      • 好的,我更新了问题。作为评论而不是答案,这可能会更好。
      猜你喜欢
      • 2023-03-15
      • 2014-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-30
      • 2019-09-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多