内容正文:
第9章 指针
第9章 指针
指针变量
野指针与空指针
指针变量作形参
指针作函数的返回值
地址参与运算
指针与一维数组
一维数组作形参
指针与二维数组++
指向指针类型的指针
main函数和命令行参数
指向函数的指针变量
使用堆空间
典型命题
指针变量作形参
这节课我们讨论指针变量作形参。
3
例9-5 分析add函数
add函数有三个形参,整型x,整型y和整型指针变量pr,函数将x和y的和存入到pr指向的存储单元。当指针变量pr作形参时,对应的实参应为一个整型地址。
add函数有三个形参,整型x,整型y和整型指针变量pr,函数将x和y的和存入到pr指向的存储单元。当指针变量pr作形参时,对应的实参应为一个整型地址。
main函数中调用add函数时,实参分别为i,j的值与变量k的地址。实参赋值给形参后,形参指针变量pr指向了变量k的存储单元。
add函数执行时,*pr是pr指向的存储单元,即变量k的存储单元。add函数将23和32的和存储到变量k的存储单元中,因此,返回main函数,变量k的值已经是55了。
4
指针变量的作用
add函数执行时,变量k还在生存期,但由
于作用域的限制,不能通过变量k使用
该存储单元。
但当main函数中将变量k的地址作为实参
调用add函数时,整型指针变量的形参pr就
指向了变量k,在add函数中,以*pr的方式
间接使用了变量k的存储单元。
指针作形参可以扩展存储单元的使用范围。
add函数执行时,变量k还在生存期,但由于作用域的限制,不能通过变量k使用
该存储单元。
但当main函数中将变量k的地址作为实参调用add函数时,整型指针变量的形参pr就
指向了变量k,在add函数中,以*pr的方式间接使用了变量k的存储单元。
指针作形参可以扩展存储单元的使用范围。
5
思考题
add函数执行时,属于程序的存储单元有哪些,怎样标识?add函数中可以使用哪些存储单元?
add函数执行时,属于程序的存储单元变量i标识的整型存储单元,变量j标识的整型存储单元,变量k标识的整型存储单元;
变量x标识的整型存储单元,变量y标识的整型存储单元,变量pr标识的整型指针存储单元。
其中变量k标识的整型存储单元也可用*pr标识。add函数中可以使用的存储单元有x,y,pr和*pr。
6
例9-4 分析下面的函数
函数有两个整型指针作形参,调用函
数时实参应为整型地址。
函数中交换了px和py指向的整型
存储单元的值。
函数的作用是交换与实参地址标识
的整型存储单元的值。
函数有两个整型指针作形参,调用函数时实参应为整型地址。
函数中交换了px和py指向的整型存储单元的值。
函数的作用是交换与实参地址标识的整型存储单元的值。
7
使用swap函数交换main函数中变量i和j的值
使用swap函数交换main函数中变量i和j的值时,只需将变量i和变量j的地址作为实参即可。
8
对比swap函数
一个实参是值,一个实参是地址。
形参为普通类型时,实参给形参赋值,可理解为把作业拍照发给别人。
形参为指针时,实参给形参赋值,可理解为把帐号和密码拍照发给别人。帐号和密码有两份,但帐号里面的钱两人共用。
交换两个整型变量的值无需使用函数,这两个函数都没有实际作用。
9
思考题
变量a的作用域在main函数中,scanf函数怎么改变了变量a的值?
实参是&a即变量a的地址,scanf函数中可以通过间接引用的方式使用变量a相关的存储单元,从而改变变量a的值。
10
思考题
分析下面的代码段
int n, *p;
p = &n;
scanf("%d", p);
分析下面的程序
scanf("%d", p);就是scanf("%d", &n);。形参为指针时,需要一个地址,指针变量的值就是地址。
程序简单模拟了scanf函数获取用户输入的一个整数的处理过程。
11
函数的返回值是地址
这节课我们讨论函数的返回值是地址的情况。
12
例9-6 分析下面的程序
test函数返回整型存储单元的地址
,即变量i的地址。
main函数中用指针变量pj存储了
这个地址,即pj指向了变量i。
然后以*pj的方式使用了变量i的存储单元。
程序运行正确 ,但有逻辑错误。
test函数返回整型存储单元的地址,即变量i的地址。
main函数中用指针变量pj存储了这个地址,即pj指向了变量i。
然后以*pj的方式使用了变量i的存储单元。
程序运行正确 ,但有逻辑错误。
13
指针变量pj是野指针
当test函数运行结束后,变量
i的生命周期已经结束了。
在main函数中,当pj指向变量i时
实际指向了已经不再属于程序的存储单元。
当test函数运行结束后,变量i的生命周期已经结束了。
在main函数中,当pj指向变量i时实际指向了已经不再属于程序的存储单元