一、地址和指针
1、 地址和指针
(1)地址:
变量地址就是存放变量的地址
(2)指针:
指针就是一个地址
2、指针变量
指针变量是用来放地址的一个变量,简单点理解就是,指针变量是存放指针的。
二、变量的指针和指向变量的指针
1、指针变量定义
类型名 *指针变量名
例如 int *p
2、指针变量的运用
(1)给指针变量赋值
定义一个指针变量和普通变量:int *p,int a=1;
然后给p赋值 p=&a;因为p为指针变量,故存放的是a的地址。
(2)输出指针变量所指的变量值。
printf("%d",*p);
(3)作为对比,我们把指针变量所存的地址输出用的是这种方式:
printf("%o",p),输出的既是变量a的地址。
(4)变量地址间的交换
int *p1,p2,p;
p=p1;p1=p2;p2=p;
(5)关于p和&a中符号的作用
其中p中的星号代表指针运算符。
&a中的&代表取地址运算符。
论证:
&*pointer_1的含义就是&a就是pointer_1;
3、指针变量作为函数参数
在讲解指针变量作为函数参数之前,我们先讲解一下,数组作为函数参数(直接举例论证,便于理解)。
(1)数组元素作为函数实参。
int a[10],m;
m=a[0];
max(m,a[2]); //调用max函数,m和a[2]都是实参函数声明在此不备注了
int max(int x,int y){
}
(2)一维数组名作为函数参数
一种情况,函数名作为形参,并指定大小
int a[10],b;
b=average(a); //调用时数组名作为实参
int average(int arrray[10]){ //形参类型要和实参一致
}
另一种情况 形参不指定大小,但是加上个数组长度参数
int a[10].b;
b=average(a,10); //此时实参为数组名和数组长度
int average(int array[],n){
}
(3)多维数组名作为函数参数
int a[3][4],b;
b=average(a); //多维数组调用函数也是直接将数组名作为参数
int average(int array[][4]){ //数组作为形参,
//第1维大小可以不填写
//C语言编译系统不检查第一维的大小
}
(4)指针变量作为函数参数
学习完数组的函数之后,学习指针变量会有一定的帮助,便于理解。
//省略了函数的声明
int a,b;
int *pointer_1,*pointer_2;
pointer_1=&a; //将变量a的地址赋值给指针变量
pointer_2=&b; //指针变量是用来存放地址(指针)的变量
swap(pointer_1,pointer_2); //指针变量作为函数实参
void swap(int *p1,int *p2){ //函数形参定义为指针类型
}
4、数组与指针
数组元素的指针就是数组元素的地址。
(1)用指针变量指向一个数组元素
int a[5]={1,2,3,4,5};
int *p;
p=&a[3];
(2)程序中数组名不代表整个数组,只代表数组首元素地址。
例如把a数组首元素地址赋值给p的方法:
p=&a[0]; //p的值就是a[0]的地址。
p=a; //p的值也代表a[0]的地址
(3)数组名作为函数参数
例如:形参实参都用数组名
int a[10],b;
b=average(a,10);
int average(int array[],n){
}
实参用数组名,形参用指针变量
int a[10],b;
b=average(a,10);
int average(int *p,int n){
}
实参和形参都用指针变量
int a[10],*p;
p=a;
average(a,10);
int average(int *p,int n){
}
实参为指针变量,形参为数组名
int a[10],*p;
p=a;
average(a,10);
int average(int b[],int n){
}
(4)二维数组指针
a[i][j]
表示形式 | 含义 |
---|---|
a | 二位数组名,指向一维数组a[0],即0行起始地址 |
a[0],*(a+0),*a | 0行0列的元素地址 |
a+1,&a[1] | 第一行起始地址 |
a[1],*(a+1) | 第1行第0列元素地址 |
a[1]+2,*(a+1)+1,&a[1][2] | 第1行第2列元素地址 |
*(a[1]+2),a[1][2] | 第1行第二列元素的值 |
int a[3][4];
printf("%d,%d",a,*a); //第0行起始地址,第0行0列元素的值
printf("%d,%d",a[0],*(a+0)); //第0行0列元素地址
printf("%d,%d",&a[0],*a[0][0]); //第0行起始地址,0行0列元素地址
printf("%d,%d",a[1],a+1); //第1行0列元素地址,第1行起始地址
printf("%d,%d",&a[1][0],*(a+1)+0); //第1行0列元素地址
printf("%d,%d",a[2],*(a+2)); //第2行第0列元素地址
printf("%d,%d",&a[2],a+2); //第2行起始地址
printf("%d,%d",a[1][0],*(*(a+1)+0)); //第1行第0列元素的值
printf("%d,%d",*a[2],*(*(a+2)+0)); //第2行第0列元素的值
(5)指向多维数组元素的指针变量
``cpp
int a[3][4]; //定义一个3行4列数组
int (*p)[4]; //指针变量指向有4列的二维数组
p=a; //p指向二位数组第0行的起始地址。
(6)数组指针做函数参数
int a[3][4];
search(*a,12); //*a代表第0行第0列元素的地址
avereage(a,2) //
int search(int *p,int n);{ //指针变量最为参数
}
int average(int (*p)[4],int n){ /(*p)[4]具有四个整形变量的一维数组名作为参数
}
三、字符串与指针
1、字符串引用方式
char string[]="I love you";
printf("%s",string);
2、字符串存取用指针方法
//输出
char string[]="I love you",*p1;
p1=string;
printf("%s\n",p1);
赋值
char *p2;
for(;p!='\0';p1++,p2++){
*p2=*p1
}
*p2='\0'
printf("%s",p2);
3、字符指针作为函数参数
(1)字符名作为函数参数
char a[]="I love you";
char b[]="I love you too";
copy(a,b);
void copy(char from[],char to[]){
}
(2)字符型指针变量作为实参
char a[]="I love you";
char b[]="I love you too";
char *from,*to;
from=a;to=b;
copy(from,b);
void copy(char from[],char to[]){
}
`(3)用字符型指针变量作为形参和实参
char a[]="I love you";
char b[]="I love you too";
char *from,*to;
from=a;to=b;
copy(from,to);
void copy(char *from,char *to){
}
四、指向函数的指针
1、定义
存放函数起始地址
2、用函数指针变量调用函数
//用函数名调用函数
int a,b;
c=max(a,b);
int max(int x,int y){
}
//用指针变量调用函数
int max(int x,int y); //函数声明
int (*p)(int,int); //定义指向函数的指针变量p
p=max; //函数入口地址赋值
int a,b;
c=(*p)(a,b);
int max(int x,int y){
}
3、指向函数定义
类型名 (*指针变量名)(函数参数表列)
例如:int (*p)(int,int)
4、用指向函数的指针作为函数参数
int fun(int x,int y,int(*p)(int,int)); //fun函数声明
int max(int,int); //max函数声明
int min(int,int); //min函数声明
int a=5;b=6;
if(a>b){
fun(a.b,max);
}else{
fun(a,b,min):
}
int fun(int x,int y,int(*p)(int,int){
}
int max(int x,int y){
}
int min(int x,int y){
}
5、返回指针值的函数
(1)定义形式
类型名 *函数名(参数表列)
(2)举例
float score[][4];
float *search(float (*p)[4],int n);
float *p;
p=search(score,4); //p收到的是个地址
float *search(float (*P)[4],int n){
float *pt;
return pt; //pt返回的也是个地址
}
6、指针数组
(1)定义
一个数组中,其元素都为指针类型的数据,成为指针数组。即每个元素存放的不是个值,而是个地址。
(2)形式
类型名 *数组名[数组长度]
(3)举例
//指针数组
int main(){
void sort(char *name[],int n);
void print(char *namep[],int n);
char *name[]={"Follow me","BASIC","Great Wall","FORTRAN","Computer design"}; //定义一个指针数组
int n=5;
sort(name,5); //通过数组名当实参调用函数
print(name,5);
system("pause");
return 0;
}
void sort(char *name[],int n){ //指针数组当形参
char *temp;
int i,j,k;
for(i=0;i<n-1;i++){ //选择法排序
k=i;
for(j=i+1;j<n;j++){
if(strcmp(name[k],name[j])>0){
k=j;
}
}
if(k!=i){
temp=name[i];name[i]=name[k];name[k]=temp;
}
}
}
void print(char *name[],int n){
int i;
for(i=0;i<n;i++){
printf("%s\n",name[i]);
}
}
7、指向指针的指针变量
int main(){
int a[5]={1,3,5,7,9};
int *num[]={&a[0],&a[1],&a[2],&a[3],&a[4]};
int **p,i;
p=num;
for(i=0;i<5;i++)
{
printf("%d",**p);
p++;
}
printf("\n");
system("pause");
return 0;
}
指向指针的变量就是指向a指针变量指向b指针变量,b指针变量指向c变量地址。
例如:
int main(){
int **p;
int a[]={1,2};
int *b[]={&a[0],&a[1]};
p=b;
printf("%d",**p);
system("pause");
return 0;
}
五、总结
使用指针的优点:
1、提高程序效率
2、在调用函数时,当指针指向的变量的值改变时,这些值能够为主函数使用,即可以从函数调用得到多个改变的值。
3、可以实现动态存储分配。