我目前正在乱搞c我在指针使用和语法区域有一些打嗝。
下面,我(尝试)创建一个指向整数数组的指针数组,然后将每个指针指向通过malloc()创建的数组。
创建数组后,然后循环遍历每个单元格,分配一个值。
现在,所有这些似乎都有效,但是当使用free()来取回内存时,程序会崩溃。
我注意到如果我在malloc()数组内存然后立即调用它们上的free(),程序执行没有问题。然而,当我malloc(),赋值和THEN调用free()时,将发生崩溃。 (分段错误)。
下面是有效的代码,malloc()然后立即free()ing
int (*ptrArr[5])[5];
for(int i=0; i<5; i++)
ptrArr[i] = malloc(sizeof(int) * 5);
for(int i=0; i<5; i++)
printf("ptrArr[%d][%x]->[%x]\n", i, &ptrArr[i], &*ptrArr[i]);
printf("\n");
for(int i=0; i<5; i++){
for(int j=0; j<5; j++){
printf("[%x](%2d) | ", &*ptrArr[i][j], *ptrArr[i][j]);
}
printf("\n");
}
for(int i=4; i>=0; i--)
free(ptrArr[i]);
以上按照我的预期执行,但是当我为单元格分配值然后尝试自由调用时,会生成分段错误:
int (*ptrArr[5])[5];
for(int i=0; i<5; i++)
ptrArr[i] = malloc(sizeof(int) * 5);
for(int i=0; i<5; i++)
printf("ptrArr[%d][%x]->[%x]\n", i, &ptrArr[i], &*ptrArr[i]);
printf("\n");
for(int i=0; i<5; i++){
for(int j=0; j<5; j++){
printf("[%x](%2d) | ", &*ptrArr[i][j], *ptrArr[i][j]);
}
printf("\n");
}
int loop = 5;
for(int i=0; i<5; i++){
for(int j=0; j<5; j++){
*ptrArr[i][j] = (loop + (i*j));
++loop;
}
}
printf("\n");
for(int i=0; i<5; i++){
for(int j=0; j<5; j++){
printf("[%x](%2d) | ", &*ptrArr[i][j], *ptrArr[i][j]);
}
printf("\n");
}
for(int i=4; i>=0; i--)
{
printf("Freeing ptrArr[%x]\n", i);
free(ptrArr[i]);
}
我想我或者误解了
int (*ptrArr[5])[5];
声明,我打算使用5个指针的数组,每个指针指向一个整数数组,或者我没有正确地为单元格赋值,而是破坏导致free()失败的内存。
任何帮助都将不胜感激,我希望这个问题清晰简洁。
感谢。
答案 0 :(得分:2)
我处理此类问题的方法是打印sizeof
各种嫌疑人,例如
int (*test[5])[5];
printf( "%zu ", sizeof(test) );
printf( "%zu ", sizeof(test[0]) );
printf( "%zu\n", sizeof(test[0][0]) );
结果是40 8 20
。 (注意,在我的机器上,int
是4个字节,指针是8个字节。)
所以这告诉我test
是一个包含5个指针的数组。从逻辑上讲,test[0]
是一个单指针。但有趣的是test[0][0]
是一个包含5个整数的数组。
如果我添加以下代码行
printf( "%zu\n", sizeof(test[0][0][0]) );
输出为4,即test[0][0][0]
是单int
。由此我们得出结论,声明int (*test[5])[5]
声明了一个三维数组,这不是你想要的。
所以让我们尝试一个更简单的声明,比如
int (*test)[5];
printf( "%zu ", sizeof(test) );
printf( "%zu ", sizeof(test[0]) );
printf( "%zu\n", sizeof(test[0][0]) );
输出为8 20 4
,也就是说test
是单个指针,test[0]
是5个整数的数组,test[0][0]
是单个int
1}}。我们得出结论,int (*test)[5]
声明了一个二维数组。
接下来的问题是我们如何为数组分配内存。如果我们这样做
test = malloc( 5 * sizeof(int) );
然后我们有一个有1行5列的数组,基本上是一维数组。
要获得包含N
行的二维数组,我们需要
test = malloc( N * 5 * sizeof(int) );
然后我们可以像这样填充,打印和释放数组
int N = 5;
for ( int row = 0; row < N; row++ )
for ( int col = 0; col < 5; col++ )
test[row][col] = (row+5)*10 + col;
for ( int row = 0; row < N; row++ )
{
for ( int col = 0; col < 5; col++ )
printf( "%2d ", test[row][col] );
printf( "\n" );
}
free( test );
答案 1 :(得分:0)
这很难解码,但就像一个好的神秘填字游戏,有一个解决方案。我已经整理了一些东西。根本问题是解除引用。
请参阅: Order of operations for dereference and bracket-ref in C
我在下面的一些工作代码中标记了该行。我在(* ptrArr [i])周围添加了括号来获取数组,然后可以将其正确地索引为(* ptrArr [i])[j]。
我还提出了一种首先声明阵列的替代方法。一个更容易验证!
#include <stdlib.h>
#include <stdio.h>
#define SIZE 5
int main()
{
// This makes things clearer :-
typedef int ArrayType[SIZE];
typedef ArrayType * ArrayPtr;
ArrayPtr ptrArr[SIZE];
for (int i = 0; i < SIZE; i++)
ptrArr[i] = malloc (sizeof (int) * SIZE);
int loop = SIZE;
for (int i = 0; i < SIZE; i++)
{
for (int j = 0; j < SIZE; j++)
{
// THIS NEXT LINE HAD THE WRONG BRACKETS IN
// *(ptrArr[i])[j] = (loop + (i * j));
(*ptrArr[i])[j] = (loop + (i * j));
printf("array has base address: %lx\n", ptrArr[i]);
printf("writing to: %lx\n", &(*ptrArr[i])[j]);
++loop;
}
}
for (int i = SIZE-1; i >= 0; i--)
{
printf ("Freeing ptrArr[%x] with address %lx\n", i, ptrArr[i]);
free (ptrArr[i]);
}
}
答案 2 :(得分:0)
for(int i=0; i<5; i++)
ptrArr[i] = malloc(sizeof(int) * 5);
这表示ptrArr[i]
是指向某些整数的指针。
*ptrArr[i][j] = (loop + (i*j));
这表示ptrArr[i][j]
是指向整数的指针。
这是什么?这两段代码的间接层数不同。
答案 3 :(得分:0)
您的第一个示例不正确,因为您正在打印不正确的数组索引。
嵌套的for循环调用它:
printf("[%x](%2d) | ", &*ptrArr[i][j], *ptrArr[i][j]);
第三个参数与ptrArr[i][j][0]
相同。
但这是不正确的。它应该是ptrArr[i][0][j]
,因为您只使用malloc调用分配了2d数组的一个内部维度:ptrArr[i] = malloc(sizeof(int) * 5);
。
你看int (*ptrArr[5])[5];
实际上是一个指向5个int数组的指针数组。 ptrArr[i]
是一个指向5个整数数组的指针。
这也意味着与&*ptrArr[i][j]
相同的第二个参数ptrArr[i][j]
应该是ptrArr[i][0]
,因为我们只分配了一个维度。
...
我们差不多完成了。首先用calloc替换malloc调用,因此我们不会打印垃圾值。然后用%p替换%x printf说明符并将它们各自的参数转换为(void *)。
通过这些更正,第一个示例打印出正确的地址和正确的值,并且没有未定义的行为。(您还可以删除多余的&*
对)
(这只是你第一个例子的修复!我甚至没有解决第二个问题。但解决方案大致相同。)