1 * 与&
之前的指针的总结漏了很重要的一句话,是关于* 和& 的定义。我觉得对于初学者来说,把这两句作为卡尺去衡量* 和& 是很有效果的,就像学Java时说的万物皆对象一样。
*:取指针所指向的对象的内容。
&:取地址运算符。
再举个简单地例子。
void swap(int *p1,int *p2){
int a ,b;
p1 = &a;
}
在上面的代码中,调用swap的时候,向方法中传递的是一个变量,那么,*p1代表的就是一个变量,那么p1就是一个指针变量,即p1是用来存地址的。所以后面想存a,就需要去取a的地址,也就会有后面的p1 = &a。&是取a得地址。所以p1 = &a的意思也就是取a变量的地址,将其赋给p1。
2指针初始化问题
void swap(int *p1,int *p2){
int *temp;
*temp = *p1;
*p1 = *p2;
*p2 = *temp;
}
上面的代码是会出问题的。问题在哪里呢?问题出在给 *temp上。将p1的值赋给temp,但是temp没有初始化赋值,很可能随机的地址上存储着系统的关键性的数据,而在这一句被替换掉了,从而导致系统其他的部分不稳定。这里的解决办法是把 *p1的值赋给一个整型的变量,即可解决问题。为什么?因为int类型的变量在定义之后调用之前如果不进行初始化赋值,编辑器会默认的帮你赋值。就不会造成前面说的随机地址的问题了。
即正确的代码应该是下面这样的。
void swap(int *p1,int *p2){
int temp;
temp = *p1;
*p1 = *p2;
*p2 = temp;
}
3 指针数组和数组指针
之前在使用形参的时候也说明了,函数中形式参数传递实参的时候其实是传递了数组的地址,今天看到了官方的解释。在C语言中规定数组名(不包括形参数组名,形参数组并不占据实际的内存单元)代表数组中首元素的的地址。因此在int a[6] = {0};中,a = &a[0];
所以用指针记录数组是用下面的方法之一
int a[10] = {0};
//第一种
int *p = &a[0];
//第二种
int *p = a;
既然数组中定义是指向了数组的第一个元素,那么我们该如何去调用数组后面的元素呢?这里还有一个规定:在C语言中,如果指针变量p已经指向数组中的一个元素,那么p+1指向同一个数组中的下一个元素,而不是简单地将地址加1.其实编辑器会自动获取指针的类型,然后在地址的值上加1*该类型的变量所占的字节数,所以就会自动跳到下一个元素了。这些我们只要了解一下就可以了,在使用的时候只要知道p++代表的是下个元素就可以了。