C语言 指针.docx
- 文档编号:27752681
- 上传时间:2023-07-04
- 格式:DOCX
- 页数:26
- 大小:42.09KB
C语言 指针.docx
《C语言 指针.docx》由会员分享,可在线阅读,更多相关《C语言 指针.docx(26页珍藏版)》请在冰豆网上搜索。
C语言指针
第十章指针
一、教学目的:
1. 掌握指针与指针变量的概念;
2. 学会指向与取址运算。
3. 掌握变量、数组、字符串、函数的指针以及指向变量、数组、字符串、函数的指针变量,并会通过指针引用以上各类型数据;
4. 熟练掌握指针作函数参数。
5. 了解返回指针值的指针函数。
6. 了解指针数组、指向指针的指针、main函数的命令行参数。
二、教学内容
1.指针与地址的概念
2.变量的指针和指针变量的指针变量
3.数组的指针与指向数组的指针变量
4.字符串的指针与指向字符串的指针变量
5.指针与函数
6.指针数组
三、教学重点
1. 指向与取址运算
2. 指向变量、数组、字符串、函数的指针变量;
3. 指向数组的指针变量的运算;
4. 指针作函数参数
四、教学难点
1. 指向变量、数组、字符串、函数的指针变量;
2. 指向数组的指针变量的运算;
3. 指针作函数参数
五、授课时间:
课时
六、教学过程
第十章指针
指针是C语言中的一个重要概念,也是C语言的一个重要特色。
正确而灵活地运用它:
1、可以有效地表示复杂的数据结构
2、能动态分配内存
3、能方便地使用字符串
4、有效而方便地使用数组
5、在调用函数时能得到多于1个的值
6、能直接处理内存地址
等等。
10.1指针和地址的概念
为了弄清指针的概念,必须弄清楚数据在内存是如何存储的,又是如何读取的?
在程序中定义的变量,在内存中都占有一定的内存单元。
一般微机C系统个整型变量分配2字节,给实型变量分配4个字节。
每个变量所占的存储单元都有确定的地址。
下面请看下例:
例如:
inta=3;
floatb=4.5;
charc=‘x’;
在内存的情况如图所示:
abc
200020022005
要访问内存中的变量,在程序中是通过变量名来引用变量的值。
例如:
printf(“%d”,a);scanf(“%d”,&b);
通过变量名访问一个变量的方式称为:
“直接访问”方式。
还有一种访问方式,就是把一个变量地址放在另一个变量中,通过先访问存放地址的这个变量,得到变量的地址,进而访问变量。
这种方式称为“间接访问”。
abc
papbpc
pa、pb,pc是一种变量,通过访问pa,pb,pc来访问a,b,c称为“间接访问”。
pa、pb,pc称为指针类型的变量。
10.2变量的指针和指向变量的指针变量
一、指针变量的定义
类型标识符*指针变量名;
例如:
int*p;
p中可以存放一个整型变量的地址。
上面定义了一个指针变量p,它和一般变量的定义不同,这时p的值是怎样?
为什么?
要想使它指向一个变量应怎么做?
请看下例!
例:
int*p,i=3;
p=&i;
说明:
1、标识符前面的“*”表示该变量为指针变量
2、一个指针变量只能指向同一个类型的变量,称为指针的基类型。
二、指针变量的引用
1.指针变量的引用基本方法:
(假已有如下的定义:
intx,*p,*q;)
第一步:
给指针变量赋值。
如:
p=&x;q=p;
注:
如果不给指针变量赋值,则此指针变量为悬空指针,指向任意变量造成程序不可知错误。
第二步:
访问指针所指的单元:
如:
*p=5;
此时*p相当于x,能参与x能参与的一切运算。
如输入、输出、算术运算、关系运算、逻辑运算、作为函数的参数等。
第三步:
对指针变量的直接运算:
如指针变量加一个整数,指针变量之间的比较等(以后讨论)。
2.C语言中有两个有关指针的运算符:
1)&取地址运算符(后跟的是一般变量)
功能:
取出一般变量的存储地址(用来赋给一个指针变量)
2)*指针运算符或指向运算符,也称间接运算符。
(后跟的是指针变量)
功能:
指向指针变量所指向的变量。
例:
int*p,i=3;
p=&i;
*p=5;
这时的*p与定义指针变量时用的*p含义不同,在定义时int*p中的*不是运算符,它只是表示其后面的变量是一个指针类型的变量,而在程序的执行语句中引用的*p,其中的*是一个指针运算符,*p表示“p指向的变量”。
3.说明:
1)如果已执行了“p=&a”,&*p的含义是什么?
&和*运算符的优先级别相同,结合方向:
自右而左。
先进行*p计算,就是变量a,再执行&运算,与&a相同。
2)*&a的含义:
先进行&a运算,得a的地址,再进行*运算,即&a指向的变量。
*&a与*p作用一样,等价于变量a。
3)(*p)++相当于a++
*p++先按p的原值进行*运算,得到a,再使p的值自增,这样p就不再指向a了。
[例10.1]使两个指针变量交换指向。
程序如下:
main()
{int*p1,*p2,*p,i1=10,i2=20;
p1=&i1;p2=&i2;
printf(“%d,%d\n”,*p1,*p2);
p=p1;p1=p2;p2=p;
printf(“%d,%d\n”,*p1,*p2);
}
[例10.2]交换两个指针变量所指向的变量的值。
程序如下:
main()
{int*p1,*p2,i1=10,i2=20,*p;
p1=&i1;p2=&i2;
printf(“i1=%d,i2=%d\n”,*p1,*p2);
*p=*p1;*p1=*p2;*p2=*p;
printf(“i1=%d,i2=%d\n”,*p1,*p2);
}
三、指针变量作函数的参数(实现的是地址传递)
实参:
地址表达式
可以是&变量、指针变量、数组名
形参:
指针变量
函数中引用:
*指针变量
功能:
“双向”传递,可以将函数中对形参的变化返回。
例1:
(用图表示数据传递的情况)
main()
{voidsub();
intx=2,y=3;
sub(&x,&y);
printf(“%d,%d\n”,x,y);
}
voidsub(int*px,int*py)
{intt;
t=*px;*px=*py;*py=t;
}
思考:
将sub函数改为如下内容结果会如何变化?
voidsub(int*px,int*py)
{int*t;
t=px;px=py;py=t;
}
注:
以前讲过“函数参数的传递是单向的,调用一次函数可以得到一个返回值”那么这里是不是“双向”传递数据呢?
不是。
这里仍然是单向的“值传递”方式。
调用函数不能改变实参指针变量的值,但可以改变实参指针变量所指变量的值。
例2:
编写一个函数,找出N个数中的最大值和最小值给主调函数。
有二种方法:
方法一、用全局变量
程序:
(略)
方法二、用指针变量
程序:
#defineN10
voidmax_min(int*max,int*min)
{inti,x;
scanf(“%d”,&x);
*max=*min=x;
for(i=1;i {scanf(“%d”,&x); if(x>*max)*max=x; if(x<*min)*min=x; } } main() {int*p,*q; max_min(p,q); printf(“max=%dmin=%d/n”,*p,*q);} 10.4数组与指针 一、指向一维数组元素的指针 1.定义一个指向数组元素的指针 方法: 定义一个数组,定义一个指针变量,将数组首地址赋给指针变量。 例: chara[100],*p; p=&a[0]; 或: p=a; 也可以: chara[100],*p=a;(初始化指针变量) 注意: 数组类型和指针基类型应一致。 2.通过指针引用数组元素 如: int*p,a[10]; p=&a[0]; 引用: *p: 引用a[0] *(p+1): 引用a[1] *(p+i): 引用a[i] 说明: C规定p+1指向数组的下一个元素。 p+1所代表的地址实际上是p+1*d,d是一个p指针所指向的元素所占的字节数。 ●● 注: 引用数组元素有三种方法: (1)下标法 (2)地址法 (3)指针法 请看下例: 分别用下标法、地址法、指针法访问数组元素 main() {inta[5]={1,3,5,7,9},i,*p; for(i=0;i<5;i++) printf(“%d”,a[i]);//下标法 *(a+i)//地址法 *(p+i)或p[i]//指针法 也可: for(i=0,p=a;i<5;i++,p++) printf(“%d”,*p); ●● 注意指针变量的运算: 假设有p=&a[0]; (1)p++p指向下一元素,不能表示为a++ (2)*(p++)先取*p,再使p加1 (3)*p++等价于*(p++) (4)*(++p)先使p加1,再取*p (5)(*p)++p所指向的元素值加1 ●● 注意数组名和指向数组的指针变量的关系 不同点: 数组名是常量而指向数组的指针变量是变量; p=a;(正确)但a=p;(错误) p++;(正确)但a++;(错误) 相同点: 引用数组元素的方法一样 p[i]、a[i](都正确) *(p+i)、*(a+i)(都正确) [例]输入若干天的温度,求平均温度。 用数组存放输入的若干个温度值,当输入完所需处理的温度后,输入“0”表示输入结束。 然后对已输入的温度求平均值。 (假设输入的温度只能为正值,用两种方法: 1、地址法2、指针法) main()/*方法一: 地址法*/ {floattemper[31],sum=0; intnum,day=0; do{printf(“Entertemperatureforday%d: ”,day); scanf(“%f”,temper+day);/*&temper[day]*/ }while(*(temper+day++)>0);/*temper[day++]>0*/ num=day-1; for(day=0;day sum+=*(temper+day) ;/*temper[day]*/ printf(“Averageis%4.1f”,sum/num); } main()/*方法二: 指针法*/ {floattemper[31],sum=0; intnum,day=0; float*p; p=temper; do{printf(“Entertemperatureforday%d: ”,day++); scanf(“%f”,p); }while(*(p++)>0); p=temper; num=day-1; for(day=0;day sum+=*(p++); printf(“Averageis%4.1f”,sum/num); } 二、数组名作函数参数 数组名作函数的参数已学过,形式参数是数组其实质是指针。 如: 函数voidsort(inta[],intn)等价于voidsort(int*a,intn) [例]从N个数的数组中找出其中最大值和最小值。 (本题不要求改变数组元素的值,只要求得到最大值和最小值,而函数只能得到一个返回值,想一想用什么办法? ) 方法一、形参、实参用数组名 intmax,min; voidmax_min_value(intarray[],intn) {int*p,*array_end; array_end=array+n; max=min=*array; for(p=array+1;p if(*p>max)max=*p; elseif(*p return;} main中的调用语句为: max_min_value(number,10); 方法二、形参、实参用指针 intmax,min; voidmax_min_value(int*array,intn) {int*p,*array_end; array_end=array+n; max=min=*array; for(p=array+1;p if(*p>max)max=*p; elseif(*p return;} main中的调用语句为: max_min_value(p,10); 归纳起来,如果有一个实参数组,想在函数中改变数组的元素的值,实参与形参的对应关系有以下4种情况: (1)形参和实参都用数组名 (2)实参用数组名,形参用指针变量 (3)实参形参都用指针变量 (4)实参为指针变量,形参为数组名 三、多维数组与指针 1、多维数组的地址 一个二维数组可以认为由若干个一维数组所组成,其中每一个一维数组包含若干个元素。 设有数组: inta[2][3],b[3];则在内存中是如何存放的呢? 请看下图: 一维数组 0号 1号 2号 a[0] a[0][0] a[0][1] a[0][2] a[1] a[1][0] a[1][1] a[1][2] a[0],a[1]是两个一维数组名。 可以将a[0],a[1]作为一维数组名使用。 二维数组名是基类型为一维数组的指针(地址),一维数组名是基类型为int或char等的指针. 二维数组的地址表示形式: (设有inta[6][5],如下) a[0][0] a[0][1] a[0][2] a[0][3] a[0][4] a[1][0] a[1][1] a[1][2] a[1][3] a[1][4] a[2][0] a[2][1] a[2][2] a[2][3] a[2][4] a[3][0] a[3][1] a[3][2] a[3][3] a[3][4] a[4][0] a[4][1] a[4][2] a[4][3] a[4][4] a[5][0] a[5][1] a[5][2] a[5][3] a[5][4] 1)(a+i)(i=0,1,2,...)是二维数组名,可以这样引用: a[2][3],(a+2)[2][3](是a[4][3]) 2)*(a+i),(a+i)[k](i=0,1,2,...)是一维数组名,可以这样引用: (*a)[5]是a[0][5](注意: 下标运算“[]”的优先级高于“*”运算,(*a)[5]! =*a[5]), (*(a+2))[4]是什么? (a[2][4])) a[2]与*(a+2)等价,因为它们都是<一维数组名>[下标]的形式。 3)*(*(a+i)+j)(i,j=0,1,2,3...)是数组元素,**a是什么? (a[0][0]),*(*(a+2)+1)是什么? (a[2][1]),是否可以表示成: *(a[2]+1)? 重要结论一: 对二维数组名做一次“*”运算,得到一维数组名,做两次“*”运算,得到数组元素;对一维数组名做一次“*”运算,得到数组元素(做两次“*”运算是错误的)。 这个结论的等价结论是: 对二维数组名做一次“[]”运算,得到一维数组名,做两次“[]”运算,得到数组元素;对一维数组名做一次“[]”运算,得到数组元素 重点: *[] 4)”&”运算是“*”运算的逆运算, 重要结论二: 对数组元素做一次“&”运算,得到一维数组名,做两次“&”得到二维数组名.对一维数组做一次”&”运算,得到二维数组名. 2、指向二维数组的指针变量 (1)指向数组元素的指针变量 定义类型数组[行长][列长]; 类型*指针名; 指向方法: 指针名=&a[i][j](√);指针名=a[i](或*(a+i))(√);指针名=a(×) 引用元素方法: *指针名 若inta[10][8],*p=a[0]; 引用a[i][j]=>*(p+i*8+j) [例]用指针变量输出数组元素的值 main() {inta[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}; int*p;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C语言 指针 语言
![提示](https://static.bdocx.com/images/bang_tan.gif)