我通过以下方法在double int指针中实例化了一个二维数组。
int **make2Dint(int rows, int columns) {
//a is our 2D array
int **a = (int **)calloc(rows, sizeof(int *));
//If we can't allocate the necessary memory, return null.
if (!a) {
return (int **)NULL;
}
//Allocate each row with the correct amount of column memory.
for (int i = 0; i < rows; i++) {
a[i] = (int *) calloc(columns, sizeof(int));
//If we can't allocate the necessary memory, return null.
if (!a[i]) {
return (int **)NULL;
}
}
return a;
}
为此,我还写了一个免费功能,如下所示
void free2DArray(void **a, int rows) {
for (int i = 0; i < rows; i++) {
free(a[i]);
}
free (a);
}
在使用我的免费功能时,(通过free2DArray(array, rows);
然而,gcc给了我一个警告。
In file included from life.c:6:0:
twoD.h:14:6: note: expected ‘void **’ but argument is of type ‘int **’
void free2DArray(void **a, int rows);
^~~~~~~~~~~
现在,我可以通过转换为void **
来消除这种情况,但this似乎表明我对void **
的使用存在问题。
C中没有通用的指向指针类型.void *仅作为通用指针使用,因为当其他指针类型分配给void *&void时,会自动应用转换(如果需要);如果尝试间接在指向void *之外的指针类型的void **值上,则无法执行这些转换。当您使用void **指针值时(例如,当您使用*运算符访问void **指向的void *值时),编译器无法知道该void *值是否为一次从其他指针类型转换而来。它必须假设它只不过是一个空洞*;它无法执行任何隐式转换。
换句话说,你玩的任何void **值必须是某个地方的实际void *值的地址;像(void **)&amp; dp这样的演员虽然可以关闭编译器,但是不可移植(甚至可能不能做你想做的事情;另见问题13.9)。如果void **指向的指针不是void *,并且如果它具有与void *不同的大小或表示,则编译器将无法正确访问它。
但是,由于我没有取消引用此指针,因此我不确定它是否存在问题。有人可以解释它是否有问题,为什么?
答案 0 :(得分:2)
没有。即使指针类型具有相同的大小和表示,C也不允许使用不同类型的别名,除非在一些特殊情况下,编译器可以并且将进行转换(优化)。如果你真的想要这样一个通用的自由循环,你可以将循环放在一个宏中,该宏在具有正确指针类型的上下文中扩展(在调用者中),但你应该真的只是避免“深度”伪二维数组
答案 1 :(得分:1)
将二维数组创建为嵌套的一维数组是不好的做法。您应该只需一步分配整个空间,free()
只需一次。
这不仅会完全回避您当前的问题,它还会为矩形(非锯齿状)2D阵列提供卓越的性能,因为所有内存都是连续的,而不是按行/列分散。