我在C中有以下代码:
double ***grid
grid = calloc(nx, sizeof(double**))
for (int i = 0; i < nx; ++i) {
grid[i] = calloc(ny,sizeof(double*));
for (int j = 0; j < ny; ++j) {
grid[i][j] = calloc(nz,sizeof(double));
}
}
我不明白为什么我们不能写grid[i]=calloc(ny,sizeof(double**))
?网格的每个成员都是“指针指针”是不是真的?我们也不应该grid[i][j] = calloc(nz,sizeof(double*))
?
当我以当前形式使用grid[i][j][k]
时,代码工作正常,但我对原因感到困惑。我是C的新手,所以我很欣赏各种形式的解释。
编辑:缺少一行:grid = calloc(nx, sizeof(double**))
答案 0 :(得分:1)
首先你错过了第一个alloc:grid = calloc(nx, sizeof(double **));
但是我不确定这是不是因为代码甚至没有编译(在grid
声明之后缺少分号所以它必须已被分配在其他地方)
然后回答你的问题,分配会在对象上返回一个指针,这会添加额外的*
,但你必须指定calloc的元素大小来进行计算(ny*sizeof(object))
grid[i]=calloc(ny,sizeof(double**))
会起作用,因为double指针上的指针大小与double的指针相同,但它并不完美。
如果您有一个像这样分配的int数组:
int *array = calloc(ny,sizeof(int *))
它可以在大多数平台上正常工作,但如果您使用的是标准32位int
的64位架构(例如,Windows 64位盒,gcc 64位编译器),那么指针是64位,它将分配两倍于你真正需要的内存。在这种情况下,正确的语法是:
int *array = calloc(ny,sizeof(int))
因为该元素是int
,它会在int
(int *
)上返回指针
所以,现在,反复来说,当你在左边添加一颗星星时,你会在右边添加一颗星星:
int **array = calloc(ny,sizeof(int *))
int ***array = calloc(ny,sizeof(int **))
依旧......
个人小故事:在人们过去使用的日子里,从32位迁移到64位时遇到了一些令人讨厌的崩溃:
int **array = calloc(ny,sizeof(int)) // WRONG!!
虽然一切都是32位,但仍有效。当sizeof(int *)
由于64位arch而增加到8个字节时,只分配了一半的大小,这可能会导致非常有趣的错误。