<C和指针---读书笔记6>

指针

指针是一种变量,和int、float、char一样,是一种基本的变量。只不过它比较抽象一些。

我们知道在C语言中,声明一个变量a、b,编译器会为其分配一个物理地址 addr_1 、addr_2,在之后的C语言中,a =1操作,是把数值1存入该 addr_1,就等价于a值变为1。b = b+1 ,是先读取 addr_2的内容,加1操作后,再写会 addr_2内。

可以这样理解: 变量出现在 =右侧,一般是 读 addr_x的内容,变量是左值,一般是 存入 addr_x。 在C语言中变量实质上就是 物理地址的代号。对变量名的操作本质上就是对 物理地址的操作。

所以 a =1 ,b=b+1,都无非是 地址的读写操作。 像float、int、char这类变量,变量名等价于物理地址,a = "address 1"   b= "address 2"

访问a就是访问 address1.   address1/2里面的内容就是a、b的值,没有其他特别的意义。

int *p 声明了一个指针变量p, 依然存在  p = "address 3" 的映射。但是p里面的内容是一个特别得信息。它是地址 "address  n“。

C语言使用    *p 间接的访问 ”address n“     使用p访问 "address 3",

 

声明和初始化 

(1)  int  *p ;  p = &a   (2) float  *p = &b ;

方法1,首先声明p是一个 "指向int"的指针变量。 然后 p = &a ,把a的地址,存入 p内。 即 p内存储的值 = address_a

方法2, 声明p是一个 "指向float"的指针变量。 是一个缩写形式。

一定要理解: 变量p自己有一个物理地址addr_p,只不过(addr_p) =  &a.

 未初始化和非法指针

因为我们经常需要对 指针变量进行间接访问,一定要保证指向的地址是一个安全可靠的。比如指针变量指向了一个未知的地址,后续盲目的

对该地址进行间接读写,很可能出现大问题。所以要保证指针--->安全地址。

非常可惜的是: 编译器对于未明确指定的指针变量不会进行分配。那我们分配到哪?最好有一个 绝对安全的地址供我们使用。

NULL指针:  NULL值在stdio.h文件有明确  #define NULL  (  (void *) 0 )   把整型0强制转为指针型,并指向void类型数据。

int *p = NULL ;  int *p =  (void *) 0  相当于   指针变量p =  0,并指向了 void。

 

指针变量的间接访问 和直接访问

int *p = &a ;    这时候  p =  10 ;这是非法的,本质原因是: 10是整型变量,p是 指针型变量,不能对等。  可以 p = (int *) 10; 把10也变为

指向整数的指针变量。

&p: 同样对变量p取地址,获得的是p的物理地址。该操作合情合法。

*p : 左值,表示存入 (P)---->  address 内。 右值,取(P)---->  address内的数据。

         * &a = 25 , 即 * (address a) = 25 即存入 a地址内。

 

指针的指针

既然指针是一个变量,自己拥有自己的地址,那完全可以再用指针指向它,。 这就是指向指针的指针,简称指针的指针

 

 

怎么声明? int **pp ;

怎么表明指向的规则?  int  *p = &a ; int **pp = &p 即可。

那么如何通过指针的指针 访问 整型变量a? 

 pp = &p

*pp  是对 指针变量p的间接操作。  *p 是完成对 整型a的间接访问。

**pp 才是最终对a的间接访问。

 

指针表达式实例

 

Char  ch =’a’;

 

Char  *cp = &ch;

 

表达式形式

左值

右值

&ch

 

获得ch变量的地址

cp

修改cp的内容,则指向位置将会变化

读取cp的内容,即获得某个间接地址

&cp

 

获得指针变量cp自己的地址

*cp

把数据存入 间接地址内

获取 间接地址 的内容

*cp+1

非法

获取 间接地址 的内容,并加1操作

*(cp+1)

把数据存入 (间接地址+1)内

获取 (间接地址+1) 的内容,

++cp

非法

Cp值加1,再返回新cp值,

同时 指针的指向位置变化

Cp++

 

Cp值加1,返回旧cp值

同时 指针的指向位置变化

*++cp

把数据存入(间接地址+1)内,

同时 指针的指向位置变化

获取 (间接地址+1) 的内容,

同时 指针的指向位置变化

*cp++

因为返回的是旧cp值,故而

把数据存入(间接地址)内,

同时指针的指向位置变化

因为返回的是旧cp值,故而

获取 间接地址 的内容

同时,指针的指向位置变化

++*cp

 

获取 间接地址 的内容,+1之后,返回值

指针的指向位置不会变化

(*cp)++

 

获取 间接地址 的内容,并返回。

指针的指向位置不会变化

++*cp++

 

获得间接地址 的内容+1,并返回

指针的指向位置变化

++*++cp

 

获得 间接地址+1 的内容,并对其加1,再返回,

指针的指向位置变化

 

 

 这只是一个表格,描述了各种运算的结果。只为加深理解。

指针的运算

指针变量主要用于 间接操作,一般对指针变量本身的操作,并不是很多,主要就是加法运算。

float  a[10] ; 

float  *p = a;

定义了一组浮点型数组,并把数组首地址赋给p。我们知道一个float 型会占用 4 bytes空间。

P = Address_of_a[0].  如果我们执行p+1,本质上是想 P = Address_of_a[1].  那么p+1 应该是  p + 1* sizeof(float)

庆幸的是,C编译器为我们进行了这个处理,使得我们可以更加方便的使用指针变量+1. 

这也是我们声明指针时,为什么要说明指针指向的是什么数据类型。它其实是为了编译器处理 sizeof(xxx)操作、

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2017-09-03 13:45  mokang0421  阅读(107)  评论(0编辑  收藏  举报