2.7 指针
2.7.1 什么是指针
只要在变量前面加上&,就表示变量的地址
#include<stdio.h>
int main()
{
int a=1;
printf("%d,%d\n",&a,a);
return 0;
}
输出结果:2686748,1
同时可以注意到,指针实际上是一个整数,事实上可以指出,指针是一个unsigned
类型整数
2.7.2 指针变量
指针变量用来存放指针(或者可以理解成地址,这个关系就跟int
型变量用来存放int
型常量相同),例如下面几个定义:
int* p;
double* p;
char* p;
正如刚才所说,指针变量存放的是地址,而&则是取地址运算符,因此给指针变量赋值的方式一般是将地址取出来,然后赋值给相应的指针变量
int a
int* p=&a
需要注意的是,int*
是指针变量的类型,而后面的p
才是变量名,用来存放存储地址,因此地址&a
是赋值给p
,而不是赋值给*p
。多个指针变量赋初值时候,由于写法上允许将*
放在所有的变量名前面,因此容易混淆,其实只要知道*
是类型的一部分就可以了
既然p
保存的是地址,那么*p
是这个地址中存放的元素,那么如果直接对*p
进行赋值,也可以起到改变那个保存的元素的功能,就像是下面这个例子:
#include<stdio.h>
int main(){
int a;
int* p=&a;
*p=233;
printf("%d,%d\n",*p,a);
return 0;
输出结果:233, 233
指针变量也可以进行减法,其中减法的结果就是两个地址偏移的距离。对一个int*
型的指针变量p
来说,p+1
是指p
所指的int
型变量的下一个int
型变量地址
2.7.3 指针与数组
可以在元素前加上取地址运算符&
来获取元素的地址,例如a[0]
的地址为&a[0]
,即数组a
的首地址为&a[0]
不过C语言中,数组名称也作为数组的首地址使用,因此上面的例子中,有a==&a[0]
若是a
作为数组a
的首地址被赋给p
,那么输出*p
其实就是输出a[0]
指针变量可以进行加减法,那么a+i
等同于&a[i]
,这是因为指数组a
的首地址偏移了i
个int
型变量的位置。但是也应该注意,a+i
其实只是地址,如果想要访问其中的元素a[i]
,需要加上*
,使其变成*(a+i)
后才能和a[i]
等价,由此可以得到一组输入素组的新颖写法:
scanf("%d",a+i);
两个int
型指针相减,等价于在求两个指针之间相差了多少个int
,由于&a[0]
和&a[5]
之间相差了五个int
,因此输出5
2.7.4 使用指针变量作为函数参数
指针类型也可以作为函数的参数类型,这时候将变量的地址传入函数。如果在函数中对这个地址中的元素进行改变,原先的数据就会被确实的改变,示例如下:
#include<stido.h>
void chage(int *p){
*p=233;
}
int main(){
int a=1;
int* p=&a;
change(p);
printf("%d\n",a);
return 0;
}
此时传入的其实是a的地址
函数在接收参数的过程中是单项一次性的值传递。也就是说,在调用swap(a,b)时候只是把``a
和b
的值传进去了,这相当于产生了一个副本,对这个副本的操作不会影响main
函数中a和b
的值
众所周知,指针变量存放的是地址,那么使用指针变量作为参数时候传进来的也是地址,只有在获取地址的情况下对元素进行操作,才能够真正的改变变量
下面这个例子不能够真正的改变变量
#include<stdio.h>
void swap(int a,int b){
int temp=a;
a=b;
b=temp;
}
int main(){
int a=1,b=2;
swap(a,b);
printf("a=%d,b=%d\n",a,b);
return 0;
}
下面这个例子能够真正的传递值
#include<stdio.h>
void swap(int* a,int* b){
int temp=*a;
*a=*b;
*b=temp;
}
int main(){
int a=1,b=2;
int *p1=&a,*p2=&b;
swap(p1,p2);
printf("a=%d,b=%d\n",*p1,*p2);
return 0;
}
下面来说说容易犯的错误写法:
void swap(int* a,int* b){
int* temp;
*temp=*a;
*a=*b;
*b=*temp;
}
在定义int*
型的指针变量temp
时候,temp
没有被初始化,指针变量temp
中存放的地址是随机的,如果该随即地址指向的是系统工作区间,那么就会出错,问题找到后就好解决了:既然因为temp
一开始没有被赋值而产生了随机的地址,那么就可以给它赋值,这样就不会有问题了
错误写法二:
void swap(int* a,int* b){
int* temp=a;
a=b;
b=temp;
}
对地址本身进行修改其实和之前传入的普通变量进行交换函数是一样的作用,没法对数据产生影响,相当于将int*
看作一个整体,传入的都只是a
和b
的地址副本
2.7.5 引用
1.引用的含义
#include<stdio.h>
/*下面使用了引用符号&,在传入参数的时候就会对原变量进行修改*/
/*注意把引用符号&与取地址运算符&区分开来,引用并不是取地址的意思*/
void change(int &x){
x=1;
}
int main(){
int x=10;
change(x);
printf("%d\n",x);
return 0;
}
2.指针的引用
#include<stdio.h>
void swap(int* &p1,int* &p2){
int* temp=p1;
p1=p2;
p2=temp;
}
int main(){
int a=1,b=2;
int *p1=&a,*p2=&b;
swap(p1,p2);
printf("a=%d,b=%d\n",a,b);
printf("p1=%d,p2=%d\n",*p1,*p2);
return 0;
}
运行结果
a=1,b=2
p1=2,p2=1