我正在学习考试,我遇到了一些我很难理解的东西。我们正在使用指针和内存分配,而我只是在弄乱事物,试图看看改变了什么。我有这段代码:
int * arr[10];
for(i=0; i<5;i++)
{
int index = i;
arr[index] = malloc(sizeof(int*));
int i = 2 * index;
*arr[index] = i;
printf("arr [%d] = %d\n", index, *arr[index]); /* should be 0, 2, 4, 6, 8 */
}
但我发现如果不使用* arr [index] = i,我使用arr [index] =&amp; i我不需要malloc
。我一直认为这两件事本质上是一回事,但必须有一些我不理解的关键区别,以保证使用malloc
。
我真的很困惑为什么我真的需要malloc
。我对内存分配相当新,我真的不明白什么时候它应该被使用(显然),并且想知道是否有人可以为我清除这一点。
答案 0 :(得分:4)
请尝试使用此代码:
int * arr[10];
for(i=0; i<5;i++)
{
int index = i;
int value = 2*i;
arr[index] = malloc(sizeof(int*));
*arr[index] = value;
}
for (i=0; i<5; i++)
{
int index = i;
printf("arr [%d] = %d\n", index, *arr[index]); /* should be 0, 2, 4, 6, 8 */
}
如果你进行了改变,你现在就会有未定义的行为。鉴于此代码仍然有效。
你有未定义的行为,因为*arr[0]
现在指向一个已经留下范围的堆栈内存。
你的malloc实际应该是malloc(sizeof(int))
。您要为int
分配空间,而不是为int *
分配空间。
答案 1 :(得分:1)
是的,我认为很难理解,因为我在for的中间重新定义了。我现在会改写代码。我写了i而不是索引和2 * i而不是重新定义的i。
int * arr[10];
for(i=0; i<5;i++)
{
arr[i] = malloc(sizeof(int));
*arr[i] = 2*i;
printf("arr [%d] = %d\n", i, *arr[i]); /* should be 0, 2, 4, 6, 8 */
}
这里你不需要动态内存,你知道将使用数组0-4。当您不知道需要多少mutch数据时,您需要动态内存。编写此代码,以便其余代码仍然有效,但没有malloc。
int array[5];
int **arr=array;
以下代码表示,数组[index]应指向我存储的内存地址。它不会复制i中的值,因此当您更改i或我被删除时,这将导致此指针有问题,以后会引起问题。你不应该这样做。
arr[index] = &i
答案 2 :(得分:1)
这样写道:
*arr[index] = i;
表示:将i
的值复制到arr[index]
指向的内存位置(在代码中先前分配)。
arr[index] = &i;
表示:将i
的地址复制到arr[index]
。
在您的代码中i
会在for循环中自动创建,并且只存在于该循环中。一旦离开循环(范围),用于存储i
的内存就可以自由地分配给任何新创建的变量。
正如sharth建议的那样,尝试查看原始for循环之外的值,以查看一些有趣的结果。
答案 3 :(得分:0)
一个关键的区别是&i
一旦i
超出范围就会停止存在(或者说,那段内存可以重复用于其他东西......这可能不会包含您认为包含的内容。)
答案 4 :(得分:0)
编辑:我在下面说你没有说明i
是如何宣布的。实际上,如果在循环中使用i
,则重新声明它,隐藏原始值。无论如何,i
将在循环结束时超出范围,或者可能在例程结束时超出范围。
您不会在此处显示i
的声明方式。但是,在大多数情况下,它是局部变量或传递给方法的参数。在任何一种情况下,该变量的空间都在堆栈上声明。您可以使用&i
获取该变量的地址,但该方法结束后该变量将消失,并且代码会将这些值从堆栈中弹出。你可能会很幸运,只要你需要,你就可以保持这个价值不变。但是,当另一种方法被调用时,该值可能会被覆盖并繁荣,您的程序最多会出现错误行为。
如果全局声明i
,你可以侥幸成功。
此外,即使在更改i
的值后,您也指向相同的地址。如果在例行程序结束时打印出数组的所有值,您会发现它们都是相同的值 - 您放入数组的最后一个值。那是因为数组中的每个条目都指向同一个位置。