列举几个例子,帮助快速入门指针:
只要是变量,在系统中肯定有内存来表示这个变量。
首先,我们将内存空间简化成是一个一个的小格子,每个格子都有一个序号(内存地址)
原则:只要是变量,就一定占格子;
只要是指针变量,就一定占4个格子。
例子1、定义三个类型的变量:
char c;
int a;
(int *) p;
int **pp;
则有:
&c = 100; 格子的序号对应的就是变量c的地址。
&a = 200; int类型的变量,他的地址就是第一个格子做对应的格子的地址。
&p = 204; 指针变量在编译的过程中,要被转化成地址串(存储单元编号),对于32位的cpu,存储单元的地址是32位。所以指针变量占4个字节。
&pp = 208;
例子2、定义一个结构体:
typedef struct{
int a;
int b;
}T_ab;
定义一个结构体类型的变量:
T_ab tTest;
则有:
&T_ab.a=300;
&T_ab.b=304;
&T_ab=300;
应用1:
int main()
{
char c=‘a’;
int a=0;
T_ab tTest={1};
int *p=0;
int **pp=0;
假设进行如下操作:
①、p =&a;
指针的值,就是地址。在这步操作之前,指针p是一个野指针,指针的地址&p=204,但是指针没有值。
进行这步操作之后,指针p的值就是变量a的地址,此时,指针p指向a的地址,*p=10,p=200,&p=204(这个值一直都不会变)。
②、*p = 0x12345678;
表示给p所指向的4字节(也就是变量a)赋值0x12345678。此时,a=12345678。
③、p = &c;
此时,*p=随机,p=100,&p=204
强调:这个操作有一个隐患,就是变量c本来只占一个字节,这样操作,会让变量c占4个字节,会覆盖掉之前变量c后面的三个字节。
④、*p = ‘A’
表示给 p存放的地址所对应的值 赋值 ’A’。此时,c=41
⑤、p = &tTest;
此时,*p = 1,p=300,&p=204
⑥、*p = &tTest;
此时,*p = 300
⑦、pp = &p;
此时:,*pp=300,pp = 204,&pp =208;
⑧、pp = 0Xabcd;
解析一下pp:
*pp可以拆分成(*pp) ,pp = 地址204所对应的值=300
再300 ,表示300这块内存所对应的值是0xabcd;即tTest.a = abcd;
}
总结一个口诀:
*变量:把变量的值作为地址,去访问这个地址所对应的值。
附一个简单的测试程序,便于理解:
```c
#include <stdio.h>
typedef struct{
int a;
int b;
}T_ab;
int main(int argc,char **argv)
{
char c='a';
int a=0;
T_ab tTest={1};
int *p=2;
int **pp=3;
printf("&c=%x,&a=%x,&p=%x,&pp=%x,&tTest=%x\n",&c,&a,&p,&pp,&tTest);
p =&a;
printf("*p=%x,p=%x,&p=%x\n",*p,p,&p);
*p = 0x12345678;
printf("*p=%x,p=%x,&p=%x,a=%x\n",*p,p,&p,a);
p = &c;
printf("*p=%x,p=%x,&p=%x\n",*p,p,&p);
*p = 'A';
printf("*p=%x,p=%x,&p=%x,c=%x\n",*p,p,&p,c);
p = &tTest;
printf("*p=%x,p=%x,&p=%x\n",*p,p,&p);
*p = &tTest;
printf("*p=%x,p=%x,&p=%x,tTest=%x\n",*p,p,&p,tTest);
pp = &p;
printf("*pp=%x,pp=%x,&pp=%x\n",*pp,pp,&pp);
**pp = 0Xabcd;
printf("*pp=%x,pp=%x,&pp=%x,pp=%x,tTest.a=%x\n",*pp,pp,&pp,pp,tTest.a);
return 0;
}