一、指针是什么
1.由于通过地址可以找到所需的变量单元,即地址指向变量单元,则可将地址形象化地称为"指针"。
二、怎样定义指针变量
1.定义指针变量的一般形式:类型名 * 指针变量名;
例如:int *a,int *pointer_1,float *pointer_2,char *pointer_3。
2.在定义指针标量时,同时对它初始化。
例如:int *pointer_1=&a,即定义指针变量pointer_1,并指向a。
注:(1)指针变量前的"*"表示该变量为指针型变量,指针变量名为pointer_1。
(2)在定义指针变量时必须指定基类型。
一个变量的指针的含义,一是以储存单元编号表示的纯地址(如编号为2000字节),一是它指向的储存单元的数据类型。
例如:a是指向整型数据的指针变量,b是指向单精度型数据的指针变量。
(3)指向整型数据的指针类型表示为"int*",读作"指向int指针"或简称"int指针"。
(4)指针变量中只能存放地址(指针),不能将一个整数赋给一个指针变量。
例如:*pointer_1=100; 此语句错误。
int *pointer, pointer=&a; 此语句正确。
3.怎样引用指针变量
(1)给指针变量赋值,例如:p=&a,即将a的地址赋给指针变量p。
(2)引用指针变量指向的变量。
(3)引用指针变量的值。
注:(1)& 取地址运算符 &a是变量a的地址。
(2)* 指针运算符 *p代表指向x变量p指向的对象。
三、通过指针引用数组
1.数组元素的指针
数组元素的指针就是数组元素的地址。
#include<stdio.h>
int main()
{
int a[10]={1,2,3,4,5,6,7,8,9,10};
int *p;
p=&a[0];
}
用一个指针变量指向一个数组元素。
在指针已指向一个数组元素时,可对指针进行自加、自减、加、减一个整数、两指针相减。
注:(1)如果指针变量p已指向数组中的一个元素,则p+1指向同一数组中的下一个元素,p-1指向同一数组中的上一个元素。
p+1是加上一个数组元素所占用的字节数。例如:数组元素为float型,则p+1代表p+1*4。
(2)如果p的初值为&a[0],则p+i和a+i就是数组元素a[i]的地址。
(3)*(p+i)或*(a+i)是p+i和a+i就是数组元素a[i]的地址。
例如:*(p+5)或*(a+5)表示的就是a[5]。
(4)如果指针变量p1和p2都指向同一数组中的元素,如执行p2-p1,结果为p2-p1的值(两地址之差)除以数组元素的长度。
例如:p2指向实数型数组元素a[5],其值为2020,p1指向a[3],其值为2012,p2-p1的结果为(2020-2012)/4=2。
3.通过指针引用数组元素
(1)下标法,例如 a[i]此类形式。
(2)指针法,例如*(p+i)或*(a+i)表示的是p[i]或a[i]。
例1:有一个整形数组a,有10个元素,要求输出数组中的全部元素。
(1)下标法
#include<stdio.h>
int main()
{
int a[10];
int i;
printf("请输入10个数:");
for(i=0;i<10;i++)
scanf("%d",&a[i]);
for(i=0;i<10;i++)
printf("%d ",a[i]);
printf("\n");
getchar();
getchar();
return 0;
}
(2)指针法
#include<stdio.h>
int main()
{
int a[10];
int i;
printf("请输入10个数:");
for(i=0;i<10;i++)
scanf("%d",&a[i]);
for(i=0;i<10;i++)
printf("%d ",*(a+i));
printf("\n");
getchar();
getchar();
return 0;
}
(3)用指针变量指向数组元素。
#include<stdio.h>
int main()
{
int a[10];
int *p,i;//定义指针变量*p;
printf("请输入10个数:");
for(i=0;i<10;i++)
scanf("%d",&a[i]);
for(p=a;p<(a+10);p++)//用指针指向当前的数组元素;
printf("%d ",*p);
printf("\n");
getchar();
getchar();
return 0;
}
其三者运行结果均为:
注:在用指针变量p来指向元素时,用p++使p的值不断改变从而指向不同的元素。
4.在利用指针引用数组元素时,有以下几种情况:
(1) p++;
*p;
p++是使p指向下一个元素a[1],然后再执行*p,得到下一个元素a[1]的值。
(2) *p++
等价于*(p++),即先引用p的值,实现*p的运算,然后再使自增。
(3)*(++p)
即先使p的值自增,再实现*p的运算。
(4)++(*p)
即p所指向的元素值加1.若p=a,且a[0]的值为3,则在执行完++(*p)后,a[0]的值为4。
注:是元素a[0]的值加1,而不是指针p的值加1。
(5)如果p当前指向a数组中第i个元素a[i],则:
1.*(p++)相当于a[i++],即先对p进行*运算,再使p的值自增。
2.*(p- -)相当于a[i- -],即先对p进行*运算,再使p的值自减。
3.*(++p)相当于a[++i],即先使p的值自增,再对p进行*运算。
4.*(- -p)相当于a[- -i],即先使p的值自减,再对p进行*运算。
四、用数组名作函数参数
表 1 以变量名和数组名作为函数参数的比较
实参类型 | 变量名 | 数组名 |
要求形参的类型 | 变量名 | 数组名或指针变量 |
传递的信息 | 变量的值 | 实参数组首元素的地址 |
通过函数调用能否改变实参的值 | 不能改变实参变量的值 | 能改变实参数组的值 |
注:实参数组名代表一个固定的地址,或者说是指针常量,但形参数组名并不是一个固定的地址,而是按指针变量处理。
例2、将数组a中n个整数按相反顺序存放。
#include<stdio.h>
void inv(int *x,int n);
int main()
{
int i,arr[10],*p=arr;
printf("The original array:\n");
for(i=0;i<10;i++,p++)
scanf("%d",p);
printf("\n");
p=arr;
inv(p,10);
printf("The array has been inverted:\n");
for(p=arr;p<arr+10;p++)
printf("%d\t",*p);
printf("\n");
getchar();
getchar();
return 0;
}
void inv(int *x,int n)
{
int *p,m,temp,*i,*j;
m=(n-1)/2;
i=x;j=x+n-1;p=x+m;
for(;i<=p;i++,j--)
{
temp=*i;
*i=*j;
*j=temp;
}
}
其运行结果为:
例3.用指针方法对10个整数按由大到小的顺序排列
#include<stdio.h>
void sort(int x[],int n);
int main()
{
int i,*p,a[10];
p=a;
printf("请输入10个数:");
for(i=0;i<10;i++)
scanf("%d",p++); //输入10个整数
p=a; //让指针变量重新指向a[0]
sort(p,10);
for(p=a,i=0;i<10;i++)
{
printf("%d ",*p); //输出排序后的10个数组元素
p++;
}
printf("\n");
getchar();
getchar();
return 0;
}
void sort(int x[],int n)
{
int i,j,k,t;
for(i=0;i<n-1;i++)
{
k=i;
for(j=i+1;j<n;j++)
if(x[j]>x[k])
k=j;
if(k!=i)
{
t=x[i];
x[i]=x[k];
x[k]=t;
}
}
}
其运行结果为:
函数sort中用数组名作为形参,用下标法引用形参数组元素。
五、通过指针引用多维数组元素
1.二维数组元素的地址
二维数组a的有关指针
表示形式 | 含义 | 值 |
a | 二维数组名,指向一维数组a[0],即0行的起始地址 | 2000 |
a[0],*(a+0),*a | 0行0列的元素地址 | 2000 |
a+1,&a[1] | 1行的起始地址 | 2016 |
a[1],*(a+1) | 1行0列元素a[1][0]的地址 | 2016 |
a[1]+2,*(a+1)+2 ,&a[1][2] | 1行2列元素a[1][2] | 2024 |
*(a[1]+2),*(*(a+1)+2) ,a[1][2] | 1行2列元素的值 | 元素值,13 |