我在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");
}
当我输入较低的数字(即&#39; 1 1&#39;)时会读取值但会崩溃,但是当我输入高数字时会崩溃(即&#39; 10 10&#39;)。
答案 0 :(得分:6)
你做了一个非常简单的语法错误
*p[i] = (double*)malloc(m * sizeof(double));
应该是
(*p)[i] = (double*)malloc(m * sizeof(double));
这是因为在C中,[]运算符的优先级高于*。
所以当你输入*p[i]
时,
它被翻译成**(p + i)
。
这意味着:您要求编译器通过i * sizeof(double**)
偏移p的地址来计算地址,这显然不是您真正想要的。
因此,为了强制编译器首先取消引用p,只需用括号括住*p
。
答案 1 :(得分:3)
运营商优先权就是答案。 *p[i]
相当于*(p[i])
。这使您可以访问位于data
指针之后的内存,这将破坏堆栈上的其他一些变量,或者完全崩溃。
您正在寻找(*p)[i]
,这将是新分配的数组中的第i个条目。
答案 2 :(得分:0)
您的alloc2d()分配的内容实际上不是2D数组,但是:
只有在编译时才能知道除最后一个维之外的所有维数时,才能使用C中的多维数组:
double a[5][11];
也许,这个程序可以帮助你理解......注意,COLUMNS是一个编译时常量,即使行是一个运行时变量:
#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;
}