3

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

#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”)时会崩溃。

4

3 回答 3

7

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

*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用括号括起来。

于 2012-10-18T15:52:22.037 回答
3

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

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

于 2012-10-18T15:54:10.377 回答
0

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

  • 1 1D n-long 指针数组,指向 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;
}
于 2012-10-18T21:47:18.757 回答