加入黑客反病毒 登录
黑客反病毒论坛 返回首页

学者无界的个人空间 http://blog.hackav.com/?12617 [收藏] [复制] [分享] [RSS]

日志

C语言中的指针(一)

热度 2已有 326 次阅读2014-8-15 21:00 |个人分类:C语言|系统分类:C与C++| C语言

小事件:
试想这样的场景,小明要打开教室的门,但门是加密的。小明知道薛老师家地址。
一 找薛老师要密码,来到薛老师家,薛老师告诉了密码。
二 找薛老师要密码,来到薛老师家,薛老师说我不知道密码,任老师知道,告诉了你任老师家地址,于是找到任老师家,任老师告诉了密码。
上面这个两个例子中。小明可以看成一个变量,他脑子中存的东西是可以变化的。
第一个例子:他存了薛老师家地址,小明就是一个指针变量。后来他存储了密码,他这个时候可以看成一个整形变量。
第二个例子:他存了薛老师家地址,但是从薛老师家只能得到任老师家地址,从任老师那才能得到密码。小明就是一个二级指针变量,访问两次,才能找到密码。
其实想一想,指针变量,二级指针变量,普通变量本质上有区别吗?他们本质不过就是一个能存东西的空间而已。
正文:
一 常量与变量
1 常量
总体来说在C语言中常量有三种说法:
  1. 一个数,比如5,3.2这些都是常量,经常被称之为字面常量。
  2. 一个宏,比如#define Pi 3.14,那么在使用Pi这个符号的时候,用的就是3.14,又叫字符常量。
  3. 一个地址,不过地址又有多种表现形式:
    • 一个地址值 0x0040000
    • 一个变量的地址,比如 int nNumber之后, &nNumber是一个常量。
    • 一个数组的首地址,比如int nArray[10]之后,nArray是一个常量。
    • 一个函数的入口地址  ,比如 void fun(){  XXXX代码  },fun是一个常量。
无论常量的样子如何变迁,用什么符号表示,本质上他们都是一个数值。
2 变量:
包含两个部分,一 变量名 二 地址空间。地址空间存储着这个变量的数值,变量名可以理解为这个地址空间的助记符。也可以说变量名是这片地址空间的抽象体。
3 变量的类型
变量是有类型的,不同类型的变量根据需要所分配的地址空间的大小不同。
4 指针变量与地址
通常我们说指针指的就是指针变量,指针变量的空间存储的是一个地址。
可能到这里,你还会迷糊,指针这个词汇很新奇,不能从日常培养出的语感,看一下就明白他的含义,那么我们不妨记住一个比较长的含义:无论什么类型的指针,它就是存储地址的变量。
5 指针类型:
一 都是存地址的,为什么还要有类型之分?不同类型的指针,会按照其类型的属性使用这段内存空间。
举个例子:int  a = 0x0000450A。在内存中其排列方式是0A450000。假如存储这个0A450000的空间首地址为0x00460000;
                 int  *p= &a; 这个时候,p中存储的就是0x00460000.
        那么:printf("%d",*p);这句话使用了指针p,用他访问它所存储的内存的时候,因为它是int型指针,那么就会访问0x00460000~0x00460003取出其中的内容就是0000000A。
二 int型指针只能存储int型变量的地址吗?
答案是否定的。
还是和刚才差不多的例子:
                 int  a = 0x0000450A;
                 char  *p= &a;    这个时候,p中存储的也是0x00460000.
                 printf("%d",*p);这句话使用了指针p,用他访问它所存储的内存的时候,因为它是char型指针,那么就会访问0x00460000这个字节的内容,也就是0A。那么就会打印出10.               
结论:不同类型的指针,会按照这个类型的属性去访问这个地址所存储的内容。
指针类型:
                1 基本数据类型的指针
               char   int  long  short  float  double 以及配合unsigned关键字得到的数据类型。它们的属性就是可以按类型去直接访问到这个地址的空间。char会直接访问1个字节,int访问4个字节。。。
                int  *p ;
                p+1所得到的就是四个字节之后的位置。
                2 结构体类型的指针
                比如一个结构体为
                struct   Test
                {
                    int         a;
                    char      b;
                    double c;
                }  
                Test是一个结构体类型,int  a;char b;double c;叫做Test结构体类型的成员。
                当定义这个类型的结构体变量,比如Test  a;占用的空间对齐之后大小为16个字节.(要了解对齐,请关注:从结构体内存模型到基类与派生类的转换)
                用指针指向这段空间之后,要使用->符号访问每一个成员,本质就是访问a的不同区域。
                那么当用结构体指针,存储char类型数据的地址,去访问这块地址的时候,会访问到char类型数据之后的空间,谁都不会知道读出来的会是什么内容。。。。。
                3 函数指针
                这种指针,对于初学者来说,是很不好理解的。其实想想,代码也要存储在内存中的,知道代码的首地址,就可以从头执行这段代码了。函数指针就有这种可以执行的属性,也就是可以通过函数指针去调用一段代码。
                扩展:所以你可以在一个数组中,写一段机器码,通过一个函数指针去调用你写的代码。没有觉得瞬间有点高大上。
                4 数组指针
                这种指针怎么说他呢?它会以数组的属性去访问空间。什么是数组的属性,就可以一行一行的访问数据。比如
                int  (*a)[10];
                a+1之后,得到的是a这个地址之后40字节的位置。
                也就有点像int  b[10][10];
                b[0][0]与b[1][0]他们的地址相差40个字节
                所以数组指针总是和二维数组联用。
                5 二级指针与多级指针
                二级指针的属性就是:我这个变量存了一个地址,这个地址所对应的空间中又存了一个地址。每一级都相当于一级指针,也就是说:
                int **p;
                p+1得到的是p这个地址往后4个字节的位置。
                (*p)+1得到的是p存的地址往后4个字节的位置。
                char **p;
                p+1得到的是p这个地址往后4个字节的位置。
                (*p)+1得到的是p存的地址往后1个字节的位置。
                假如二级指针存储的是一个地址,而这个地址空间中没有存储一个有效地址。*p没有问题是一个地址,**p有问题啦,因为访问到
                莫名其妙的地方了。
                一涉及多级指针,就容易陷入语法深渊,分析分析这是什么意思:
                int*((* a)[10]);
                那么涉及多级指针,多维数组,是不是更头晕呢?记住一点,一层一层的分析,他是个什么。另外不用这几个东西不耽误写出高效的代
                码,所以能不碰还是不碰的好。
                6 不如再说说指针数组
                指针数组并不是指针。这里提到他,主要是因为它总和数组指针搞混,不如记住:指针数组是数组,数组指针是指针。
                指针数组呢,是一个数组,数组的每一个元素都是一个指针,定义方式int  *a[10]。可以从符号的结合性去看看第4条和第6条语法的区别。


路过

鸡蛋
2

鲜花

握手

雷人

刚表态过的朋友 (2 人)

全部作者的其他最新日志

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 加入黑客反病毒

关闭

站长推荐上一条 /2 下一条

Archiver|手机版|小黑屋|黑客反病毒组织 ( 京ICP备12031837号-2 )  

GMT+8, 2018-8-18 04:25 , Processed in 0.251878 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

返回顶部