第六章 指针
这一章,就明显触痛刚開始学习的人敏感之处了。我也是在一段时间不用C以后就会对这一部分生疏,好吧,事实上是对高级指针那块生疏。
当然这一部分总有非常多借鉴之处。比方数组范围的问题等,要不我也不会大夏天的这么虐自己看这样的书。
总结:
指针变量的值并不是它所指向的内存位置所存储的值,而是保存了指向的变量的地址。须要通过间接訪问符*来訪问指向的变量的值。
单单声明一个指针。而并不进行初始化。是不会分配内存的。所以在指针运行间接訪问之前。指针必需进行初始化。
要么指向某个变量、要么去malloc一个内存。
NULL指针就是不指向不论什么东西的指针。除了NULL指针之外。再也没有不论什么内建的记法标识指针常量。除非是用 volatile 0x00...这么命名。这在如今PC系统看来是不可想象的。在极少见的情况下,我们偶尔须要用到指针常量。
指针能够作为一个左值来用,由于指针标识了一个特定内存位置。
比方: ptr = ¶ ?
? ? ? ? ? *ptr = para;
在指针值上能够运行一些有限的算术运算。你能够把一个整型值加到一个指针上,也能够从一个指针减去一个整型值。在这两种情况下,这个整型值会进行调整。原值将乘以指针目标类型的长度。
须要注意的是。指针的大小就是一个字节,因此对一个指针加1,让它指向下一个空间。这与该指向的变量是float double没有半毛钱的关系。
指针间的相互运算。仅仅实用于数组之中其结果才是能够预測的,对于那些非数组元素的运算,最好不要去用,肯定是非法的,仅仅只是IDE没有报错。
当减法的时候,假设指针指向数组首元素之前的位置。非法。
当加法的时候,假设指针指向数组末元素之后的一个位置,合法,但再往后。非法。一般不要触碰这个底线。
假设两个指针都指向同一个数组的元素。它们能够相减,表示数组中相隔多少个元素。
假设两个指针不指向同一个数组。那么它们相减是错误的。
关于关系运算。最简单最常见的是測试它们相等或者不相等。
假设两个指针都指向同一个数组的元素,那么它们还能够用>=,>,<,<=这几个元素。
警告:
1、错误地对一个未初始化的指针变量进行解引用。
int *a;
...
*a = 12;
a指向一个位置量,假设a是静态的。那么它会被初始化为0,假设a是自己主动的,那么它不会被初始化,不管哪种情况,仅仅声明一个指针变量是不会开辟一个内存空间。
window比較温和,一般就是终止程序。倒霉的时候会产生保护性异常(General Protection Exception)。
unix里面管其叫做 memeory fault。它提示程序试图訪问一个未分配给程序内存的位置。
一定要注意,在调用指针时候,确保它们已经被初始化。
2、错误地对一个NULL指针进行解引用。
int *a;
a = NULL;
temp = *a; //wrong!
3、向函数错误地传递NULL指针。 ?
这样的错误纯属活该,在传递之前。必需检測函数的有效性。
4、未检測到指针表达式的错误,从而导致不可预料的结果。
比方:当声明一个指针的时候,假设已经知道被初始化什么地址了,就初始化。否则就初始化为NULL。这是个好事,大大节省调试时间。
5、对一个指针进行减法运算,使它非法地指向了数组第一个元素的前面的内存位置。
见上。
编程提示:
1、一个值应该仅仅具有一种意思。
2、假设指针并不指向不论什么有意义的东西,就把它设置为NULL。
问题?
5、 int i[10];
? ? ? int *p = & i[0];
? ? ? int offset;
? ? ? p += offset ; (a)
? ? ? p += 3; ? ? ? ? (b)
a/b差别是什么?
答:求值过程没有差别。可是a多一步数组越界的检查。
6、int array[ARRAY_SIZE];
? ? ?int *pi;
? ? ?for( pi = &array[0]; pi < &array[ARRAY_SIZE];)
*++pi = 0;
错误在哪?
答:目的是将array数组清零,可是array[0]没有清零。由于++前缀了。
同一时候,多清了一个零。array[ARRAY_SIZE-1]后面一个内存空间也被清零了。