标签:
指针困扰了无数学习编程的人,或许你的老师会告诉你,指针比较难学。
然而,不要被吓到,本宝宝就是当时被老师的话唬住所以学习指针那章的时候都没心情听课。(说得像讲别的内容时我听了似的,just kidding)
导致了学习链表的时候各种卧槽。
*************************** 基本介绍 **************************
程序中数据的使用往往是以变量的形式出现,每个变量都对应若干存储单元,变量的值存储在存储单元中,通过对变量的引用和赋值就可以使用或修改存储在存储单元中的数据。
——《C语言程序设计与实践》
如果一个变量的地址存放在另一个变量中,则存放地址的变量叫指针变量。
指针就是地址,指针运算就是根据地址得到那个地址下存放的数据。
常用的是一级指针,二级指针一般比较少用。
*************************较为形象的理解 ************************
比如:让你去教学楼A214教室找一个人a,A214就是这个人所在的地址,A214就是一个一级指针,你有这个地址,你就能找到这个人。
类似的,二级指针则是:A214教室里没有这个人,但是门上贴着另一个地址:A215,然后你来到A215,找到了这个人,那么A214就是一个二级指针
因为你要经过两次寻找,才能找到这个人。
**************************** 进入正题 *************************
指针的声明及初始化:
1 //第一种:声明并初始化
2
3 int a = 3;
4 int *p = a;
5 /* 定义指针变量 p 为指向整型数据 a 的指针,这一句写成 int *p = &a 同样是对的,一个意思,这里的 *号只是表示P是一个指针,并不是做指针运算。*/
6
7 //第二种:仅声明
8
9 float *p; //定义一个指向单精度型数据的指针变量 p
10
11 // 书面一些讲, 定义一个指针变量的一般形式是:
12 // <类型> *<变量标识符>
13 // 变量标识符,就像上面的 p
14 // 指针的英文是pointer
一段简单的代码
1 #include <stdio.h>
2 int main()
3 {
4 int x,y;
5 int *px,*py,*p;
6 px = &x; // &是取地址符号
7 py = &y;
8 x = 21;
9 y = *px;
10 //指针运算,即取出 px 这个地址(也就是 x 的地址)对应的值赋给 y
11
12 p = &y;
13 printf("%d,%d,%d,%d,%d\n",*px,*py,x,y,*p);
14 return 0;
15 }
16
17 /* 输出结果:分别是对 px 做指针运算得到的21,对 py 做指针运算得到的
18 21,x的值21,y的值21,对p做指针运算得到y的值21 */
注意事项:
1. 指针不能指向一个没有被定义的变量,这也是第一行代码存在的原因。
2. 指针不能指向具体的数值,例如:int *p = 3,这是错误的。
3. 分清楚当前指针是在做指针运算还是表明该指针指向某个变量。
第三条个人认为非常重要,不然会理解不了很多东西,不要一看到 * 号就觉得是在做指针运算(即把那个地址对应的值给取出来),因为有的时候只是表明那个变量的指针身份,表指向而已。
*********************** 指针与数组 **********************
数组的名字就是它的首地址,这个首地址是不能被改变的,数组可以转换成指针。
1 int a[3];
2 for(int i = 0; i<3; i++)
3 {
4 *(a+i) = i;
5 // *(a) = i; a++; 这样写是错误的,a是指针常量,常量不能被修改
6 }
******************* 指针常量 *********************
形如:int * const pa = a;
仔细观察一下,*号在const前面,说明pa是常量。
1 int a = 1;
2 int b = 3;
3 int *const pa = &a;
4 a = b; // 这句话也可以用*pa = b来代替
5 // 如果写 pa = &b 显然是不行的,因为pa这个指针是常量指针
6 printf("%d",*pa);
7 // 输出结果是3
说白了,不能写pa = xxxx,但是可以写*pa = xxxx
************************* 常量指针 ************************
形如:int const *pa = a;
这里int和const谁前谁后都是一样的
1 int a = 2;
2 int b = 3;
3 const int *pi = &a; //仔细观察可以看出 pi 是指向常量的指针
4 pi=&b; //注意这里,pi可以在任意时候重新赋值一个新内存地址
5 b = 30; //如果这里用*pi=30,是错误的
6 printf( “%d”, *pi ) ;
7 // 输出是30
有人会疑惑,这明明是指向常量的指针,为什么指向的那个数据却从2变成了30?
好吧,是因为pi存的地址是可以变的,其实只是说不能写*pi = xxxx 而已,不能这样改变,但是可以用别的方式改变。
对比上面两端代码看看,应该就明白了。
************************ 为什么指针变量要分类型 *******************
有的人疑惑,如果初始化指针指向一个已经声明过的变量,是不是可以不用写指针类型?因为指针类型就是它指向的数据的类型啊?
1 int a = 3;
2 char ch = 1; //如果这里写‘1‘后面会输出49,因为是ASCII码,ASCII码中的字符1对应十进制49
3
4 char *p = &ch;
5 printf("%d",*p);
请记住:指针的类型决定这个指针会读多少个字节的数据出来。(至于怎么读,从低往高读还是从高往低读,数据存储是从高到低还是从低到高,我还没有理解清楚)
想了解的朋友可以到这里看理解较深的大大写的数据变量在内存中的存储方式:http://blog.sina.com.cn/s/blog_abc091cc0101h0a3.html
堆区,栈区,静态存储区详解:http://my.oschina.net/lxrm/blog/513794
所以声明了类型会更安全。
p读取一个字节的数据,也就是ch的内容 :1
然而如果把第四行改成int *p = &ch,最后输出的就不一定是1了,这要看内存分配,这个指针会读取4个字节(32位平台下int型占4个字节)的数据,非常危险。
***************************** 持续更新中 ***************************
标签:
原文地址:http://www.cnblogs.com/rootandshaw/p/5088898.html