我正在学习C,现在我撞墙了。我很难理解指针。
想象一下,我有这段代码:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define DELTA 33
int calls, seed=356;
int sum_ds(int a){
int d=DELTA;
calls++;
return a+d+seed;
}
int main() {
int num;
int *ptr;
int **handle;
num = 14;
ptr = (int *)malloc(2 * sizeof(int));
handle = &ptr;
*(*handle+0) = num;
*(*handle+1) = num+1;
*ptr = num-2;
ptr = #
*ptr = sum_ds(num-2);
}
让我们逐步了解。
1 - int调用创建一个名为calls的变量,并且不对其进行初始化,因此它包含垃圾。它存储在DATA上,假设存储器地址为0xFFAA。
2 - int seeds创建一个名为种子的变量,用整数356初始化。它存储在DATA上,让我们说内存地址为0xFFAB。
3 - int num创建一个名为num的变量,并且不对其进行初始化,因此它包含垃圾。它存储在STACK上,假设存储器地址为0xFFAC。
4 - int * ptr创建一个指向int的指针,并且不为其分配任何地址。它存储在STACK上,假设存储器地址为0xFFAD。
5 - int ** handle创建一个指向int指针的指针,并且不为其指定任何地址。它存储在STACK上,假设存储器地址为0xFFAE。 (很多人在这里写道)
6 - num = 14进入地址0xFFAC并在其上存储数字14。它是在STACK中完成的。
7 - ptr =(int *)malloc(2 * sizeof(int))在HEAP上,为2个整数分配内存大小,并存储第一个内存字节的地址(比如说0xFFZZ)(在STACK上) ptr所以现在* ptr指向那个内存地址。
8 - handle =&amp; ptr handle现在指向ptr。我相信它现在指向0xFFZZ上的任何东西(很多人在这里)
9 - *(* handle + 0)= num指向int指针的指针,现在指定的值为num(14)(许多人在这里许多人都不知道)
10 - *(* handle + 1)= num + 1指针的指针加上一个int,现在它的值被赋值为num + 1(15)(许多人在这里多了许多)
11 - * ptr = num-2 ptr的值点被赋值为num - 2(12)。我相信它会进入内存地址0xFFZZ并存储数字12。
12 - ptr =&amp; num ptr现在指向num,我相信它现在指向0xFFAC。
13 - * ptr = sum_ds(num-2)ptr指向的值是sum_ds的返回值。我相信0xFFAC它被分配了401(12 + 33 + 356)
这是对的吗?
答案 0 :(得分:4)
1 - int调用创建一个名为calls的变量,并且不对其进行初始化,因此它包含垃圾。它存储在DATA上,假设存储器地址为0xFFAA。
2 - int seeds创建一个名为种子的变量,用整数356初始化。它存储在DATA上,让我们说内存地址为0xFFAB。
一个小细节:sizeof(int)
大于1(在大多数主流平台上都是4,所以第二个地址不能比第一个高1。除此之外,AFAIK到目前为止你是正确的。< / p>
3 - int num创建一个名为num的变量,并且不对其进行初始化,因此它包含垃圾。它存储在STACK上,假设存储器地址为0xFFAC。
4 - int * ptr创建一个指向int的指针,并且不为其分配任何地址。它存储在STACK上,假设存储器地址为0xFFAD。
另一个小细节:在大多数主流平台上,堆栈向下增长,因此第4个地址将小于第3个。除此之外,AFAIK到目前为止你是正确的。 (此外,数据段,堆和堆栈上的地址在现实生活中会有很大不同。)
7 - ptr =(int *)malloc(2 * sizeof(int))在HEAP上,为2个整数分配内存大小,并存储第一个内存字节的地址(比如说0xFFZZ)(在STACK上) ptr所以现在* ptr指向那个内存地址。
要挑剔,'Z'不是十六进制数:-)所以我们说它是0x1000
而不是。
8 - handle =&amp; ptr handle现在指向ptr。我相信它现在指向0xFFZZ上的任何东西(很多人在这里)
不,handle
现在包含ptr
的地址,即0xFFAD
。 间接地 - 通过ptr
- 确实指向0x1000
(在您的示例中为0xFFZZ
)。
9 - *(* handle + 0)= num指向int指针的指针,现在指定的值为num(14)(许多人在这里许多人都不知道)
基本上是正确的。您使用的符号并不是最容易处理的,这使您更难以了解正在发生的事情。在第8步之后,*handle
相当于ptr
。由于指针和数组在许多常见情况下可以互换,*(ptr + 0)等同于ptr[0]
,也等同于*ptr
。
10 - *(* handle + 1)= num + 1指针的指针加上一个int,现在它的值被赋值为num + 1(15)(许多人在这里多了许多)
与前一点类似,您实际上正在分配ptr[1] = num+1
。请注意,虽然ptr
为int*
,但ptr
和ptr + 1
之间的地址差异等于sizeof(int)
,如上所述,通常为4 *ptr
11 - * ptr = num-2 ptr的值点被赋值为num - 2(12)。我相信它会进入内存地址0xFFZZ并存储数字12。
是的,这会覆盖步骤9中设置的值。
12 - ptr =&amp; num ptr现在指向num,我相信它现在指向0xFFAC。
正确。
13 - * ptr = sum_ds(num-2)ptr指向的值是sum_ds的返回值。我相信0xFFAC它被分配了401(12 + 33 + 356)
正确。由于上一步使num
等同于num = sum_ds(num-2)
,因此此调用也等同于{{1}}。
答案 1 :(得分:1)
由于calls
在任何函数之外,因此它是static
变量。静态变量初始化为0。
由于num
是局部变量(auto
存储类),因此未初始化。
在您的第9点,*(*handle+0) = num;
可能最容易解释为handle = &ptr
,因此*handle = ptr
,因此这基本等同于*(ptr+0) = num;
,这是ptr[0] = num;
(反过来)相当于+1
。
对于第10点,你会得到几乎相同的东西,除了两个案例中的ptr[1] = num+1;
,所以它是*ptr=num-2;
。
对于第11点,*(ptr+0)
会覆盖第9点所写的内容 - 即* ptr与ptr[0] = num-2;
相同,因此这相当于ptr
在第12点,您的num
已设置为num=sum_ds(num-2);
,这是正确的。这意味着在第13点,分配相当于{{1}}
答案 2 :(得分:1)
变量有一个地址,并且在该地址存储的是您刚刚放置的值:
int a = 10;
右?
指针是一种存储另一个变量地址的变量。 所以......
int a = 10;
int *p = &a;
这意味着“p”存储了具有您想要使用的值的“a”的地址。
执行以下代码,您将了解: printf(“%p%p%d%d \ n”,p,&amp; a,* p,a);