0%

《C和指针》笔记-第六章-指针

第6章 指针

6.1 简介

第6章-指针

更多详细见语句思维导图

6.2 收获

6.2.1 指针的图形表示方法

1
2
3
4
int a = 112, b = -1;
float c = 3.14;
int *d = &a;
float *e = &c;

image-20200527150719557

6.2.2 严禁向未初始化的指针变量赋值

1
2
3
4
// 这是非法的
int *a;
...
*a = 12;

6.2.3 关于空指针NULL

为了测试一个指针变量是否为NULL,你可以将它与零值进行比较。之所以选择零这个值是因为一个源代码约定。就机器内部而言,NULL指针的实际值可能与此不同。在这种情况下,编译器将负责零值和内部值之间的翻译转换。

尽管这个技巧在C程序中极为常用,但它违背了软件工程的原则,用一个单一的值表示两种不同的意思是件危险的事,因为将来很容易无法弄清哪个才是它真正的用意。在大型程序中,这个问题更加严重,因为你不可能在头脑中对整个设计一览无余一种更为安全的策略是让函数返回两个独立的值:首先是个状态值,用于提示查找是否成功;其次是个指针,当状态值提示查找成功时,它所指向的就是查找到的元素。

不要对空指针NULL进行间接访问

6.2.4 指针、间接访问和变量的一些事

1
*&a = 25; //没意义的代码,a = 25

不要指针!和整数运算!混用!!!!!

1
2
*d = 10 - *d; //合法,但不要这样用!
d = 10 - *d; //非法

6.2.5 嘿嘿嘿,编译器,错误和警告

当我们实际使用的变量类型和应该使用的变量类型不一致时,编译器会发出抱怨,帮助我们判断这种情况。这些警告和错误信息是我们的朋友,编译器通过产生这些信息向我们提供帮助。尽管被迫处理这些信息是我们很不情愿干的事情,但改正这些错误(尤其是那些不会中止编译过程的警告信息)确实是个好主意。在修正程序方面,让编译器告诉你哪里错了比你以后自己调试程序要方便得多。调试器无法像编译器那样准确地查明这些问题。

6.2.6 指针的指针

1
2
3
int a = 12;
int *b = &a;
int *c = &b;

image-20200527160027739

1
2
3
int a = 12;
int *b = &a;
int **c = &b;

6.2.7 指针表达式

运算的左值和右值

  • 左值需要一个存储的地址,要求多

  • 右值

一些操作:

fig1: 指针变量

image-20200527160801418

fig2: 取地址符

image-20200527160814841

fig3: 间接访问符

image-20200527160826208

fig4: *的优先级高于+,先执行间接访问操作,我们就可以得到它的值,再加1,得到最终结果为字符'b'

image-20200527160834749

fig5: 先地址加1,再间接访问

image-20200527160845943

fig6: 先地址加1,再将更新后的地址赋给左值。表达式的结果是增值后的指针的一份拷贝。这份拷贝的存储位置并未清晰定义,所以它不是一个合法的左值。

image-20200527160859438

fig7: 它先返回cp值的一份拷贝然后再增加cp的值

image-20200527160926452

fig8: 增加间接访问符后,左值就合法了。间接访问操作符作用于增值后的指针的拷贝上,所以它的右值是ch后面那个内存地址的值,而它的左值就是那个位置本身

image-20200527161005913

fig9: ++操作符的优先级高于*。1)++操作符产生cp的一份考本;2)然后++操作符增加cp的值;3)最后,在cp的拷贝上执行间接访问操作。

image-20200527161020984

fig10: 在这个表达式中,由于这两个操作符的结合性都是从右向左,所以首先执行的是间接访问操作,然后,cp所指向的位置的值增加1,表达式的结果是这个增值后的值的一份拷贝。

image-20200527161038197

6.2.8 指针运算

image-20200527161934310

算术运算

第一种:指针 ± 整数

标准定义这种形式只能用于指向数组中某个元素的指针,并且这类表达式的结果类型也是指针。这种形式也适用于使用malloc函数动态分配获得的内存。

第二种:指针 - 指针

只有两个指针都指向同一个数组中的元素时,这才是允许的。返回两个指针之间的距离。

关系运算

< <= > >=

使用关系操作符的前提,它们都指向同一个数组中的元素

6.2.9 警告的总结

  1. 不要对一个未初始化的指针变量进行解引用
  2. 不要对一个NULL指针进行解引用
  3. 不要向函数错误地传递NULL指针
  4. 未检测到指针表达式的错误,会导致不可预料的结果
  5. 对一个指针进行减法运算,使它非法地指向了数组第1个元素的前面的内存位置。

6.2.10 编程好习惯

  1. 一个值应该只具有一种意思
  2. 如果指针并不指向任何有意义的东西,就把它设置为NULL