——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-
1、指针的概念
在内存中,内存单元的编号也叫做地址,根据内存单元的编号或地址可以找到所需的内存单元,通常也把这个地址叫做指针,所以,地址就是指针。
2、指针变量
在C语言中,允许用一个变量来存放指针,这种变量称为指针变量。所以,指针变量的值就是某个内存单元的地址。
注意:指针本身是一个地址,是固定不变的。而指针变量是存放一个地址,是一个变量,是可以改变的。
1)指针变量的定义
指针变量定义一般形式为:
类型说明符 *变量名;
例: int *p;
long *p1;
float *p2;
注意:
1–定义指针变量“*”必须要有,它代表定义的是一个指针变量
2–指针变量只能用于存放地址,不能存放数值或字符
3–指针变量也有全局和局部变量之分
2)指针变量的初始化
如果一个指针只有定义而没有初始化,那么我们称之为“野指针”。
指针变量的初始化同样有两种形式,分别是定义的同时初始化以及先定义后初始化。
1–定义的同时初始化
例: int *p=&a ; //定义一个指针变量p,这个指针变量存放的是a的地址,也可以成为p指向了a
2–先定义后初始化
例: int *p1; p1=&b ; //先定义一个指针变量p1,然后让p1指向b
一般情况下,指针变量最好在定义的同时对其初始化
3、指针的应用
应用:交换两个变量的值
(1)先看一下不使用指针的情况:
void s(int p1,int p2){
int temp;
temp=p1;
p1=p2;
p2=temp;
}
int main(){
int a=8;
int b=9;
s(a,b);
priuntf("交换后的a=%d,b=%d\n",a,b);
}
上述代码在不使用指针作为形参时,我们会发现输出结果a=8,b=8。a和b的值并没有改变,这是因为我们只在s()函数体内对形参进行了交换,这个结果不会影响到实参,所以主函数中输出的结果仍然是实参的值,并没有改变。
(2)接下来,使用指针作为形参
void s(int *p1,int *p2){
int *temp;
temp=p1;
p1=p2;
p2=temp;
}
int main(){
int a=8;
int b=9;
s(a,b);
priuntf("交换后的a=%d,b=%d\n",a,b);
}
我们知道,指针变量存放的是变量的地址,因此,题中形参p1和p2实际上存放的是a和b的地址,所以,在s()函数中对p1和p2的交换实际上是对地址进行了交换,所以此时形参的改变影响了实参,输出结果也就对a和b做了交换。
因此,通常指针作为函数的形参进行使用,通过把形参定义为指针变量来间接访问调用者的变量。
4、二级指针
如果一个指针变量存放的是另外一个指针变量的地址,此时,我们称这个指针变量是个二级指针。
定义二级指针如下:
int *p1=&a ;
int **p2=&p1 ;
所以,可以说p2指向了p1,而p1指向了a
5、数组指针
数组指针就是存放一个数组的指针,这个指针指向一个数组。
例: int s[5]={1,2,3,4,5};
int *p=s; //此时的p就是一个数组指针
数组指针的使用:
通常我们使用数组指针来访问数组中的元素:
1–如:p+1 表示指向数组的下一个元素
p-1 表示指向数组的上一个元素
数组指针应用之数组的逆序排列:
void nixu(int s[],int len){
int *p=s; //定义一个指针,指向数组s
int i=0,j=len-1;
int temp;
while(i<j){
temp=*(p+i);
*(p+i)=*(p+j);
*(p+j)=temp;
i++;
j--;
}
}
int main(){
int ss[10]={1,2,3,4,5,6,7,8,9,10};
nixu(ss,10);
for(int i=0;i<10;i++){
printf("逆序结果是:%d\t",ss[i]);
}
}
6、指针变量之间的运算
通常两个指针变量之间的运算有减法运算和关系运算。
只有指向同一个数组的两个指针变量之间才能运算,否则运算毫无意义。
1–减法运算
(1)0x0006-0x0003=3(意义不大)
常见的用法:两个指针都指向同一个数组,可以用来:
i.判断两个指针变量指向的元素是否连续
ii.判断指向同一个数组的两个指针变量之间相隔几个元素
例:int a[5]={1,2,3,4,5};
int *p=a;
int *p1=&a[3];
此时p1-p=3就是代表p1和p之间相隔3个元素