我正在学习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种子创建一个名为种子的变量,用整数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)存储在ptr上(在STACK上),所以现在 ptr指向该内存地址 .
8 - handle =&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 =&num ptr现在指向num,我相信它现在指向0xFFAC .
13 - * ptr = sum_ds(num-2)ptr指向的值是sum_ds的返回值 . 我相信0xFFAC它被分配了401(12 33 356)
这是正确的吗?
3 回答
一个小细节:
sizeof(int)
大于1(在大多数主流平台上都是4,所以第二个地址不能比第一个高1 . 除此之外,AFAIK到目前为止你是正确的 .另一个小细节:在大多数主流平台上,堆栈向下增长,因此第四个地址将小于第三个 . 除此之外,AFAIK到目前为止你是正确的 . (此外,数据段,堆和堆栈上的地址在现实生活中会有很大不同 . )
为了挑剔,'Z'不是十六进制数:-)所以让我们说它是
0x1000
而不是 .不,
handle
现在包含ptr
的地址,即0xFFAD
. 间接地 - 通过ptr
- 它确实指向0x1000
(在你的例子中是0xFFZZ
) .基本上是对的 . 您使用的符号并不是最容易处理的,这使您更难以了解正在发生的事情 . 在步骤8之后,
*handle
相当于ptr
. 由于指针和数组在许多常见情况下可以互换,*(ptr 0)相当于ptr[0]
,也相当于*ptr
.相近前一点,您实际上正在分配
ptr[1] = num+1
. 请记住ptr
是int*
,因此ptr
和ptr + 1
之间的地址差异等于sizeof(int)
,如上所述,通常为4 .是的,这会覆盖步骤9中设置的值 .
正确 .
正确 . 由于上一步使
*ptr
等效于num
,因此此调用也相当于num = sum_ds(num-2)
.由于
calls
在任何函数之外,因此它是static
变量 . 静态变量初始化为0 .由于
num
是局部变量(auto
存储类),因此未初始化 .在你的第9点,
*(*handle+0) = num;
可能是最容易破译的,因为要记住handle = &ptr
,因此*handle = ptr
,所以这基本上相当于*(ptr+0) = num;
,这反过来相当于ptr[0] = num;
.对于第10点,你会得到几乎相同的东西,除了两个案例中的
+1
,所以它说ptr[1] = num+1;
.对于第11点,
*ptr=num-2;
覆盖了第9点写的内容 - 即* ptr与*(ptr+0)
相同,所以这相当于ptr[0] = num-2;
在第12点你是正确的,
ptr
已被设置为指向num
. 这意味着在第13点,分配相当于num=sum_ds(num-2);
变量具有地址,并且在该地址存储的是您刚刚放置的值:
对?
指针是一种存储另一个变量地址的变量 . 所以...
这意味着“p”存储具有您要使用的值的“a”的地址 .
执行下面的代码,你就会明白:printf(“%p%p%d%d \ n”,p,&a,* p,a);