我昨天在SO上遇到question,希望在C中动态分配2-D数组。
其中一个答案是以这种方式分配:
int (*place)[columns] = malloc(rows * sizeof *place);
这除了美丽之外,还带来了一个问题。问题如下:
以下是我分配4x4
的代码 int (*arr)[4] = (int (*)[4]) malloc(4 * sizeof *arr);
printf("%d\n", sizeof arr); //Dynamic 2-D array by above method
int **arr1 = (int**) malloc(4 * sizeof(int*));
for(int i = 0; i < 4; i++)
arr1[i] = (int *) malloc(sizeof(double));
printf("%d\n", sizeof arr1); //Usual dynamic 2-D array
int *arr2 = (int*) malloc(4 * sizeof(int));
printf("%d\n", sizeof arr2); //Dynamic 1-D array
通常的输出是:
4
4
4
但是,如果我尝试打印sizeof *arr
,sizeof *arr1
和sizeof *arr2
,则输出为:
16
4
4
我不明白为什么会这样。知道为什么sizeof *arr
的输出是16
?在第一种情况下如何分配内存?
此外,当我尝试打印arr
和*arr
的地址时,两个打印值都相同。 *arr
表示“价值”arr
。那么这是否意味着arr存储了自己的地址,即它指向自身(我认为不可能)?我有点困惑。知道我哪里错了吗?
感谢您的帮助!
答案 0 :(得分:3)
但是,如果我尝试打印
sizeof *arr
,sizeof *arr1
和sizeof *arr2
,我会16
,4
和4
。< / p>
其中:
int (*arr)[4];
int **arr1;
int *arr2;
您必须使用的是32位计算机,而不是64位计算机。
arr
的类型是指向4 int
'数组的指针。当你取消引用它时,你得到一个'4个数组int
'。传递给sizeof
时,数组的大小为16(4 * sizeof(int)
)。大多数情况下,当您引用数组时,类型将调整为“指向数组的第0个元素的指针”,但sizeof()
是该规则的主要例外;它将数组视为一个数组,并返回整个数组的大小。
arr1
的类型是指向int
'的指针。当您取消引用它时,您会得到一个“指向int
”的指针。传递给sizeof
时,指针大小为4(sizeof(int *)
)。
arr2
的类型是指向int
'的指针。当您取消引用它时,您会得到int
。传递给sizeof
时,int
的大小为4。
好!我得到了大部分。但是......当我
sizeof arr2
时,为什么不是输出16?
詹姆斯在评论中指出:
因为
sizeof(arr2)
缩减为sizeof(int*)
,而32位计算机上的arr2
为4。
也就是说,int mat1[4][4];
int (*mat2)[4][4];
是一个指针;在32位计算机上,指针的大小为4。
此外,arr是'指向4 int数组的指针',即单个指针。那我怎么得到一个4×4矩阵。
您可以使用以下任何一种:
sizeof(mat1)
第一个是直接的4×4矩阵。 int
的结果在32位计算机上将是64(并且大多数64位计算机都会发生)。
第二个是指向sizeof(mat2)
的4×4矩阵的指针。 mat2
的结果在32位机器上为4; int
是一个指针(指向sizeof(*mat2)
的4×4矩阵),因此它的大小为4,与其他每个对象指针相同(实际上,与每个函数指针的大小相同)虽然C标准不保证函数指针和对象指针的大小相同;但POSIX确实保证了这一点。
mat2
的结果是int
指向的对象的大小,它是{{1}}的4×4矩阵,因此大小再次为64。
答案 1 :(得分:1)
在32位系统中,它需要4个字节或32位来唯一地标识每个存储器地址。指针不仅仅是地址的持有者。所以需要4个字节。在第一种情况下,arr是一个长度为4的指针数组,因此需要4 * 4 = 16个字节。在另外两种情况下,arr1和arr2只是一个指针。所以他们需要4个字节。