指针是c语言的一个重要概念,指针类型是c语言最有特色的数据类型:
*利用指针编写的程序可使调用函数共享变量或数据结构,实现双向数据通信;
*可以实现内存空间的动态存储分配;可以提高程序的编译效率和执行速度。
(1)指针的基本概念及指针变量的定义
1.基本概念
计算机的内存是以字节为单位的连续的存储空间,每个字节都有一个编号,这个编号称为地址。由于内存的存储空间是连续的,因此编号地址也是连续的。
变量名与内存中的一个地址相对应。
直接按变量的地址存取变量值的方式称为直接存取方式。
先通过一个变量a得到另一个变量b的地址,然后再进行存取变量值的方式得到b的值的方式称为间接存取方式。
2.定义方法
指针变量定义的一般形式
类型说明符 *标识符
*指针变量定义形式中的星号*不是变量名的一部分,它的作用是用来说明该变量是指针变量。
*如果一个表达式的值是指针类型的,即是内存地址,则称这个表达式是指针表达式。数组名代表数组的地址,是地址常量,也是指针表达式。
(2)指针运算
1.赋值运算
功能:将指针表达式的值赋给指针变量,即用指针表达式的值取代指针变量原来存储的地址值。
赋值运算符右侧的指针表达式指向的数据类型和左侧指针变量所指向的数据类型必须相同。
2.取地址运算
&标识符
功能:执行该表达式后返回"&"符后面名为"标识符"的变量(或数组元素)的地址值。
标识符只能是一个除register类型之外的变量或者数组元素。
int *e;int d;e=&d;
scanf("%d",e)等于scanf("%d",&d);
3.取内容运算
*指针表达式
"*指针表达式"的功能与"*"号后面"指针表达式"所指向的变量和数组元素等价。
取内容运算符"*"是单目运算符,也称为指针运算符或者间接访问运算符。
1 #include<stdio.h> 2 3 int main(){ 4 int x,*p; 5 x=40; 6 p=&x; 7 printf("%d %p ",x,p);//输出x的值和p的值(也就是x的地址) 8 x=78; 9 //*p=x;这个语句可有可无 10 printf("%d %d",x,*p); 11 return 0; 12 }
4.指针表达式与整数相加相减运算
p+n或p-n
表达式p+n的值=p的值+p所指向的类型长度*n;
表达式p-n的值=p的值-p所指向的类型长度*n;
只有p+n和p-n都指向连续存放的同类型数据区域,例如数组,指针加、减整数才具有实际意义。
5.自增自减运算
++p;p++;--p;p--;
都是使p指向下一个数据。
6.同类指针相减运算
得到两个同类型指针之间数据元素的个数
7.关系运算
比较指针变量所存的地址值的大小关系
1 #include<stdio.h> 2 3 int main(){ 4 int s=0,a[10],*p,*q; 5 for(p=a+9,q=a;p>=q;p--){ 6 scanf("%d",p); 7 } 8 q=a+10; 9 p=a; 10 while(p<q){ 11 s+=*p; 12 ++p; 13 } 14 printf("%d ",s); 15 return 0; 16 }
8.强制类型转换运算
(类型说明符*)指针表达式
功能:将"指针表达式"的值转换成"类型说明符"类型的指针
1 float q,*i=&q; 2 int *p; 3 p=(int *)i+1;//是将i的值转换成与p同类型的指针。如果i的值是无符号十进制数, 4 //则(int *)i+1指在整数基础上加上一个float型长度值
9.空指针
在没有对指针变量赋值之前,指针变量存储的地址值是不确定的,它存储的地址值可能是操作系统程序在内存中占据的地址空间中的一个地址,也可能是某一常驻内存的系统应用程序所占据的一个地址,还可能是内存中还没有分配使用的一块空间中的地址。因此,没有对指针变量赋初值而直接使用指针变量p进行scanf("%s",p);和*p表达式;形式的赋值运算可能会产生不可预料的后果,甚至会导致系统无法正常运行。
为了避免上述问题,通常会给指针变量付一个初值0.并把它成为空指针变量。
p=' ';p=0;和p=NULL;三个语句等价。' '的ASCII码值为0;NULL是在studio.h文件中定义的常数,其值为0。
(3)指针变量与一维数组
1.指针变量与一维数组之间的联系与区别
相同点:指针变量与一维数组不仅都可以用来处理内存中连续存放的一系列数据,而且采用统一的地址计算方法访问内存。因此任何使用下标变量完成的操作都可以使用指针变量来实现。数组名代表数组的首地址,其值为数组第一个元素的地址,一个一维数组名就是一个指向该数组第一个元素的指针。
不同点:指针变量是地址变量,可以改变其本身的值;而除了作为形参的数组名外,其它数组名是地址常量,地址值不能改变,不可以给除了作为形参的数组名之外的其他数组名赋值;用数组存取内存中的数据是通过其每个元素来实现的,而用指针变量存取内存中的数据是通过连续地改变指针的指向来实现的。
若有定义int a[5],*p=a,i;则有以下等价形式:
p[i]、*(p+i)、*(a+i)、a[i]四个表达式等价,都表示数组元素a[i];
&p[i]、p+i、a+i与&a[i]四个表达式等价,都表示数组元素a[i]的地址。
1 #include<stdio.h> 2 3 int main(){ 4 char s1[20],s2[20],*p1=s1,*p2=s2; 5 scanf("%s,",s1); 6 for(;*p1!='