1. 山雨欲来风满楼(指针要来了)
您(假如是颖颖)现在处于7#216教室,如果您的心上人(假如是彬彬)来看望您,假设有两种情况存在:
(1)他只知道您的名字
(2)他知道您当前所处的位置
哪一种情况下,他找到您的效率最高?
我们现在要去某个地方(例如七十二潭),常常先打开百度地图,规划好路线,其实这个路线恰恰就是定位目的地所处的位置。如果仅仅知道目的地,则需要费一番功夫才能到达。
大一来报到时,给你说7号楼,你也找不到呀,但如果给你提供了具体路线,你就可以轻易到达。
先来看一个程序,运行一下看看结果。
#include<stdio.h>
int main()
{
int a=4;
printf("%d\n",a);
printf("%x\n",&a);
return 0;
}
我们知道,预计int a=4; 定义了一个整型变量a,系统会在内存中为a开辟空间,则该空间的名称为a,4为该空间中存储的数据。从运行结果可知,给a开辟的空间的首地址为12ff44。根据前面的分析,我们想到:可以根据变量名a来找到a,显然也可以根据地址12ff44来找到a呀!那么,如何根据地址来找到a呢?人是有智能的,可以根据地址去找寻。但计算机该怎么办呢?
2. 指针驾到,速来接驾
针对上述程序,采用指针如下:
#include<stdio.h>
int main()
{
int a=4;
int *p;
p=&a;
printf("%d\n",a);
printf("%d\n",*p); //*p是对指针变量p所指向的变量进行引用
*p=9;
printf("%d\n",a);
return 0;
}
因为a为int,想通过a的地址来访问a,则需要定义一个指针变量p,int* p;(p为变量名,*告诉编译器p为指针变量,int则说明p指向的空间里面存放的是int类型的数据。
这里所说的指向是一个形象化的描述,因为p的空间中存放的是a的地址,根据该地址可以找到a,所以形象地认为p指向了变量a的空间。
需要注意:(1)指针和指针变量的区别:指针是地址,而指针变量是存放地址的变量。指针变量也有自己的地址。
#include<stdio.h>
int main()
{
int a=4;
int *p;
p=&a;
printf("%x\n",&a); //变量a在内存中的地址
printf("%x\n",p); //变量p空间中存放的数据
printf("%x\n",&p); //变量p在内存中的地址
return 0;
}
也可以采用格式%p输出地址值。可以根据sizeof§看看指针变量所占的字节数。
思考:
double a=3.5;
double* p=&a;//把a的地址赋值给指针变量p
p=a;//这条语句合法吗?
3. 指针性格开朗,广泛交友
3.1指针与变量
1. 通过指针变量给所指向的变量赋值
#include<stdio.h>
int main()
{
int i=2,j=3,*p,*q;
p=&i;
q=&j;
printf("i=%d,j=%d\n",i,j);
printf("*p=%d,*q=%d\n",*p,*q);
scanf("%d%d",p,q);
printf("i=%d,j=%d\n",i,j);
printf("*p=%d,*q=%d\n",*p,*q);
return 0;
}
通过scanf("%d%d",p,q);给i和j输入了新的数据。
2. 可以改变指针变量的指向
#include<stdio.h>
int main()
{
int i=2,j=3,*p,*q,*m;
p=&i;
q=&j;
printf("%d,%d\n",*p,*q);
m=p;p=q;q=m;
printf("%d,%d\n",*p,*q);
return 0;
}
通过三条语句m=p; p=q; q=m;改变了p和q的指向。
3. 通过指针变量来改变其所指向的变量的值
#include<stdio.h>
int main()
{
int i=2,j=3,*p,*q,m;
p=&i;
q=&j;
m=*p;*p=*q;*q=m;
printf("%d,%d\n",*p,*q);
return 0;
}
通过三条语句m=*p;*p=*q;*q=m;改变了p和q所指向空间的数据。
你是否想起了函数那一章的swap()交换函数???
3.2指针与一维数组
针对求最值问题,讲述指针对一维数组的三种操作形式。
1. 第一种形式,指针变量法:*指针变量
#include<stdio.h>
int main()
{
int a[10]={1,5,3,8,6,12,90,0,13,5},i,*p;
int max,min;
max=min=a[0];
for(p=a+1;p<a+10;p++)
{
if(*p>max)//if(a[i]>max)
max=*p;//max=a[i];
if(*p<min)//if(a[i]<min)
min=*p;//min=a[i]
}
printf("max:%d\nmin:%d\n",max,min);
return 0;
}
该形式,需要不断改变指针变量p的指向。
想一下,既然数组名a表示数组的首地址,a+1表示a[1]元素的地址,能否像指针变量p那样,对a执行a++操作呢????
2. 第二种形式,首地址法:*(首地址+偏移量)
#include<stdio.h>
int main()
{
int a[10]={1,5,3,8,6,12,90,0,13,5},i,*p;
int max,min;
max=min=a[0];
for(p=a,i=1;i<10;i++)
{
if(*(p+i)>max)//if(a[i]>max)
max=*(p+i);//max=a[i];
if(*(p+i)<min)//if(a[i]<min)
min=*(p+i);//min=a[i]
}
printf("max:%d\nmin:%d\n",max,min);
return 0;
}
该形式,并未改变指针变量p的指向,语句p=a;使得p指向数组a的首地址,采用p+i的方法来表示a[i]的首地址,进而通过*(p+i)获得a[i]元素的值。
3. 第三种形式,下标法:数组名[下标]
#include<stdio.h>
int main()
{
int a[10]={1,5,3,8,6,12,90,0,13,5},i,*p;
int max,min;
p=a;
max=min=p[0];
for(i=1;i<10;i++)
{
if(p[i]>max)
max=p[i];
if(p[i]<min)
min=p[i];
}
printf("max:%d\nmin:%d\n",max,min);
return 0;
}