SlideShare a Scribd company logo
1 of 83
武汉大学
UNIT ELEVEN
UNIT 11 一级指针
——指针基本篇
UNIT ELEVEN
思考几个问题?
指针就像英文中的代词,此时指代一个对象,但
随后又指代另一个对象。
1. 指针有哪些用途?
2. 和其他高级语言比较,C语言中的指针较为复
杂,请问这样设计有什么好处?又有什么不方便
之处?
3. 如何正确理解“C语言中数组与指针等价”这
个说法?
UNIT ELEVEN
本讲内容提纲
1. 什么是指针
 数据组织方式:指针的用途
 什么是指针:直接访问和间接访问
 定义指针变量
2. 指针变量的初始化
 指针运算符
 空指针和空类型指针
 动态分配内存
 指针变量的初始化
3. 指针运算
 指针赋值
 指针转换
 指针算术运算
 指针比较
4. 地址参数:指针形参模拟引用调用实现双向传递
UNIT ELEVEN
1、什么是指针
UNIT ELEVEN
1.1、数据组织方式(内存)
…...
…...
2000
2001
2002
2005
内存
1
2003
每个内存单元(每个字节)有一个编号-----地址
每个内存单元中都存放一个
字节的二进制编码----内容
01011101
如何简化内存的使用?
 基本数据类型,需要存放一个数据
(字符型、整型、浮点型等),采用方
法:划分内存的“标准间”;
 构建复杂的数据存储结构,实现方
法:……
UNIT ELEVEN
1.1、数据组织方式
(单个数据)
…...
…...
2000
2001
2002
2005
内存
1
2003
每个内存单元(每个字节)有一个编号-----地址
i
k 程序编译或函数调用时为其分配内存单元
变量是对程序中数据
存储空间的抽象
程序中:
short int i;
float k;
UNIT ELEVEN
1.1、数据组织方式
(单个数据)
…...
…...
2000
2001
2002
2005
内存
1
2003
每个内存单元(每个字节)有一个编号-----地址
i
k 变量i的地址是:2000
变量k的地址是:2002
程序中:
short int i;
float k;
UNIT ELEVEN
1.1、数据组织方式
(集合数据)
存储结构,组织物理内存的方式之一:顺序存储结构
例如,某个班级共30个
学生,考了《高级语言
程序设计》,计算平均
成绩。
85
67
98
……
0
1
29
……
score
short int score[30];
适用于数据元素个数固定的情况
UNIT ELEVEN
1.1、数据组织方式
(集合数据)
存储结构,组织物理内存的方式之一:顺序存储结构
例如,某个课堂的学生,考了《高级
语言程序设计》,计算平均成绩。
 假设一个课堂学生人数最多200人;
short int score[200];
适用于数据元素个数固定的情况
如果数据元素的个数不确定,怎么办?  浪费内存空
间;
 扩展数据元
素个数时,
必须修改源
程序。
UNIT ELEVEN
1.1、数据组织方式
(数据集合)
存储结构,组织物理内存的方式之一:链式存储结构
例如,某个课堂的学生,考了《高级语言程序设计》,
计算平均成绩;学生人数不确定。
适用于数据元素个数不确定的情况
下一个节点的地址
UNIT ELEVEN
1.1、数据组织方式
(数据集合)
存储结构,组织物理内存的方式之一:链式存储结构
 可构建各种复杂的数据存储方式;
 按用户需要分配内存:数据结构中数据元素的个
数不受限;
 扩展数据元素个数时,不必修改源程序。
适用于数据元素个数不确定的情况
UNIT ELEVEN
1.1、数据组织方式
(数据集合)
存储结构,组织物理内存的方式之一:链式存储结构
适用于数据元素个数不确定的情况
动态数据结构:节点数可根据需要临时调整;
 链表
 二叉树
 树
 图
 ……
内存地址:为构
成各种动态数据
结构穿针引线!
UNIT ELEVEN
1.2、 指针和指针变量
 指针:一个变量的地址;
 指针变量:专门存放变量地址的变量。
…...
…...
2000
2004
2006
2005
整型变量count
17
变量countptr
2001
2002
2003
2000
指针
指针变量
变量的内容
变量的地址
UNIT ELEVEN
1.2、 指针和指针变量
 指针:一个变量的地址;
 指针变量:专门存放变量地址的变量。
指针变量
变量
变量地址(指针)
变量值
指向 地址存入
指针变量
…...
…...
2000
2004
2006
2005
整型变量count
17
变量countptr
2001
2002
2003
2000
UNIT ELEVEN
1.3、 直接访问和间接访问
 直接访问:按变量名直接存取变量值
 间接访问:通过存放变量地址的变量去访问变量
17
count
变量count
直接引用数
据值17
直接访问
17
count
countptr
间接访问
指针countptr间
接引用数据值17
UNIT ELEVEN
1.3、 直接访问和间接访问
 直接访问:按变量名直接存取变量值
 间接访问:通过存放变量地址的变量去访问变量
例 count=3; 直接访问
指针变量
…...
…...
2000
2004
2006
2005
整型变量count
17
变量countptr
2001
2002
2003
2000
例 *countptr=20; 间接访问
3
20
UNIT ELEVEN
1.4、 定义指针变量
type *name
 name:指针变量名称;
 *:指针变量的标志;
 type:指针变量指向对象的数据类型;
 type *:地址本没有类型,C语言规定type *为指针变量
name的数据类型
17
count
countptr
int count , *countptr;
countptr = &count;
*countptr = 17 ;
*countptr
UNIT ELEVEN
1.4、 定义指针变量
type *name
name:指针变量;
*name:指针变量name指向的对象;
 定义的是指针变量name;
 没有定义指针指向的对象,*name.
17
count
countptr
int count , *countptr;
countptr = &count;
*countptr = 17 ;
*countptr
UNIT ELEVEN
1.4、 定义指针变量(使用要点)
type *name
 name:指针变量,编译系统自动分配;
 *name:指针变量指向的对象,编译系统不会自动分配。
 指针变量在使用前必须初始化:确保指针变量指向明确
的、合法的对象。
count
countptr
int count , *countptr;
*countptr = 17 ;
×越界使用内存
?
UNIT ELEVEN
2、指针变量
的初始化
UNIT ELEVEN
2.1、 指针运算符
*address
指针运算符*,内存地址为address的数据单元:
 address:指针(地址)表达式。
&variable
地址运算符&,变量variable的地址:
 variable:变量,有左值的表达式。
int count , *countptr;
countptr = &count;
*countptr = 17 ;
UNIT ELEVEN
2.1、 指针运算符(范例)
例题8-1 使用指针运算符&和*的演示范例。教材217 ~218页
/*使用指针运算符&和*的演示范例。源程序:LT8-1.C*/
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int a,*aptr; /*定义整型变量a,指针变量aptr*/
a=10;
aptr=&a; /*把a的地址赋给指针变量aptr*/
printf("变量a的地址是:%p,变量aptr的值是:%pn",&a,aptr);
printf("变量aptr的地址是:%pn",&aptr);
printf("变量a的值是:%d,变量*aptr的值是%d:n",a,*aptr);
printf("&*aptr的值是:%pn*&aptr的值是:%pn", &*aptr,
*&aptr );
system("PAUSE");
return 0;
} /*end main*/
UNIT ELEVEN
2.1、 指针运算符(范例)
例题8-1 使用指针运算符&和*的演示范例。
/*使用指针运算符&和*的演示范例。源程序:LT8-1.C*/
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int a,*aptr; /*定义整型变量a,指针变量aptr*/
a=10;
aptr=&a; /*把a的地址赋给指针变量aptr*/
printf("变量a的地址是:%p,变量aptr的值是:%pn",&a,aptr);
printf("变量aptr的地址是:%pn",&aptr);
printf("变量a的值是:%d,变量*aptr的值是%d:n",a,*aptr);
printf("&*aptr的值是:%pn*&aptr的值是:%pn", &*aptr,
*&aptr );
system("PAUSE");
return 0;
} /*end main*/
UNIT ELEVEN
2.1、 指针运算符(范例)
例题8-1 使用指针运算符&和*的演示范例。
/*使用指针运算符&和*的演示范例。源程序:LT8-1.C*/
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int a,*aptr; /*定义整型变量a,指针变量aptr*/
a=10;
aptr=&a; /*把a的地址赋给指针变量aptr*/
printf("变量a的地址是:%p,变量aptr的值是:%pn",&a,aptr);
printf("变量aptr的地址是:%pn",&aptr);
printf("变量a的值是:%d,变量*aptr的值是%d:n",a,*aptr);
printf("&*aptr的值是:%pn*&aptr的值是:%pn", &*aptr,
*&aptr );
system("PAUSE");
return 0;
} /*end main*/
UNIT ELEVEN
2.2、 空指针
空指针,NULL,表示不指向任何对象:
 指针类型的“零”值;
 在stdio.h中定义,表示全0 比特的二进制码;
 技术角度看,就是指向内存位置0的指针。
0、0.0、‘0’、NULL,哪个才是正确的空指针?
int *p=NULL;
*p=8; /*严重错误!*/
UNIT ELEVEN
2.2、 空指针
0、0.0、‘0’、NULL,哪个才是正确的空指针?
 长度不同:
 0、0.0、‘0’、NULL,这些全都是完全由0比特组成,
但长度不同;
 0.0 通常8字节长 ; ‘0’ 1个字节长;0 2个或4个
字节长;
 NULL 由本地系统决定长度,存储一个地址的长度;
 类型不同,C编译系统在生成编译错误时按照它们的类型区
别对待。
UNIT ELEVEN
2.3、 空类型指针
空类型指针:void *
 void *p;
表示不指定p是指向哪一种类型数据的指针变量;
空类型指针用于表示指针指向对象的类型未知。当内
存的语义不清楚时,空类型指针常用来表示原始内存。
 使用时需要强制类型转换。
例 char *p1;
void *p2;
……
p1=(char *)p2;
p2=(void *)p1;
UNIT ELEVEN
2.4、 动态分配内存
静态内存分配:
全局/静态变量:程序编译时分配的;
 非静态的局部变量:使用栈空间。
程序运行
过程中不
能之间内
存空间
动态内存分配,程序在运行过程中获取内存的方法;
 动态分配库函数;
 动态分配库函数从堆中取得内存;
 用来构建动态数据结构。
UNIT ELEVEN
2.4、 动态分配内存
(分配整块存储空间)
void *malloc( size_t size);
 stdlib.h头文件中定义;
 size_t:本地系统使用的无符号整型类型;通常被定义
为uinsigned int或者unsigned long;
功能:在堆中分配一个size字节的连续内存空间;
函数的返回值:所分配存储区域的起始地址。如没有足
够的存储空间分配,则返回0(记为NULL)值。
UNIT ELEVEN
2.4、 动态分配内存
(分配整块存储空间)
void *malloc( size_t size);
int *p;
p=(int *)malloc(sizeof( int ) );
if( p == NULL )
{
printf(“Out of memory.n”);
exit( 1 );
}
UNIT ELEVEN
2.4、 动态分配内存
(分配整块存储空间)
void *malloc( size_t size);
int *p;
/*分配10个整数的连续内存*/
p=(int *)malloc(10*sizeof( int ));
if(!p){ /*分配内存失败*/
printf(“Out of memory.n”);
exit(1);
}
p
UNIT ELEVEN
2.4、 动态分配内存
(可清除的存储空间分配)
void *calloc( size_t n , size_t size);
 函数的功能:在堆中分配n个为size字节的连续空间,
并将该存储空间自动置初值0。
 函数的返回值:分配存储区域的起始地址。如分配不
成功,则返回NULL值。
 n :表示对象的个数;
 size :每个对象占用内存单元的字节数。
UNIT ELEVEN
2.4、 动态分配内存
(可清除的存储空间分配)
void *calloc( size_t n , size_t size);
long *lptr;
lptr = (long * )calloc( 5 , sizeof( long ));
if( !lptr )
{
printf(“Out of memory.n”);
exit(1);
}
lptr
UNIT ELEVEN
2.4、 动态分配内存
(动态存储空间释放)
void free( void * ptr);
 函数的功能:释放由pt所指向的存储空间;
 此函数无返回值;
 ptr:通常为动态分配获得的内存地址;注意不要使用
无效指针,否则将破坏自由表;
 如果不是用free释放内存,则在程序执行结束时自动释
放内存;
 不要使用已经释放的“悬垂指针”。
UNIT ELEVEN
2.4、 动态分配内存
(调整动态存储空间)
void *realloc( void * ptr, size_t size );
 ptr: 是已经由malloc或calloc函数分配的存储区的指针;
 size: 是重新分配的存储区的大小(字节数);
 新存储区包含着和旧存储区相同的内容,如果新存储
区较大,则新增加的部分未被初始化。
返回值:是新存储区的首地址;如果没有足够的内存
空间则返回NULL,此时旧存储区内容不变。
UNIT ELEVEN
2.4、 动态分配内存
(调整动态存储空间)
void *realloc( void * ptr , size_t size );
long *lptr;
lptr = (long * )calloc( 5 , sizeof( long ));
if( !lptr )
{
printf( “Out of memory.n”);
exit(1);
}
lptr = (long * )realloc( lptr , 3 * sizeof( long ));
UNIT ELEVEN
2.5、 指针变量初始化
type *name = initialization;
 不要使用未初始化的指针变量:
 全局/静态指针变量未初始化,系统自动初始化为NULL,此
时指向对象不存在;
 自动指针变量未初始化,原来存储在内存空间中数据被保留;
此时指针指向的对象没有意义。
 initialization:
 NULL:不指向任何对象
 已经定义的地址或指针;
 动态分配内存。
UNIT ELEVEN
2.5、 指针变量初始化
type *name = initialization;
int x=31;
int *ptr1=&x, *ptr2, *ptr3= NULL;
31
ptr1 x ptr2
?
ptr3
UNIT ELEVEN
2.5、 指针变量初始化
例题8-2 使用动态分配的数组保存字符串,要求用户从
标准控制台输入字符串,然后反向输出该字符串。220页
/*使用动态分配的数组保存字符串,并反向输出该字符
串。源程序:LT8-2.C*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
int a;
char *s; /*定义字符指针s*/
printf("n输入一个字符串,反向输出!nn");
UNIT ELEVEN
2.5、 指针变量初始化
s=malloc(80);
if(!s)
{
printf("Memory request failedn");
exit(1);
}
gets(s); /*输入字符串*/
/*反向输出字符串*/
for(a=strlen(s)-1 ; a>=0 ; a-- )
putchar(s[a]);
UNIT ELEVEN
2.5、 指针变量初始化
printf(“nn”);
free(s); /*释放内存*/
system("PAUSE");
return 0;
} /*end main*/
UNIT ELEVEN
3、指针运算
UNIT ELEVEN
3.1、 指针赋值
ptr1 = ptr2
 ptr1:指针变量;
 ptr2:指针变量或者地址表达式;
 限制:ptr1和ptr2两者数据类型必须相同。
int a,*aptr1,*aptr2;
aptr1=&a;
aptr2=aptr1;
/*aptr1、aptr2都指向指针变量a。*/
UNIT ELEVEN
3.1、 指针赋值
ptr1 = ptr2
同类型的指针可相互赋值;
任何类型的指针都可赋给空类型指针(void *);
空类型指针(void *指针)和空指针(NULL)可以直
接赋给任何类型的指针变量;
可以将一个类型的指针赋给另一种类型的指针,但这
涉及到指针转换的问题。
赋值运算符需要将右侧的指针强制转换为左侧的指针
类型之后,才能完成赋值运算。
UNIT ELEVEN
3.2、 指针转换
void *指针转换
void *指针代表原始内存,因此又称一般指
针。
转换为void *指针,或者将void *指针转换为
其他类型指针,无需使用强制类型转换。
UNIT ELEVEN
3.2、 指针转换
其他类型指针转换
void *指针之外的其他类型指针相互转换时,必须使
用强制类型转换。
double x=100.01, y; //存储:71 3d 0a d7 a3 00 59 40
int *p;
p=(int *)&x;
y=*p; /*变量y的值为?*/
因为:p指向的对象类
型为int,*p指用了int类
型的空间
UNIT ELEVEN
3.3、 指针算术运算
(指针加、减一个整数)
该表达式的值为p1当前执行对象的下面第d个对象。
+d表示向后移动d个*p1的内存空间,因此,p1+d的值
等于p1+sizeof(*p1)*d;
-d表示向前移动d个*p1的内存空间大小。
p1+d
UNIT ELEVEN
3.3、 指针算术运算
(指针加、减一个整数)
例如,有如下定义:
short int *p1;
short score[10]
={84,65,77,60,88,86,92,93,70,66};
p1=&score[0];
1998
2000 84
2002 65
2004 77
2006 60
2008 88
2010 86
2012 92
2014 93
2016 70
2018 66
2020
p1
p1+1
p1-1
p1++; p1的值为2002
p1--; p1的值为1998
UNIT ELEVEN
3.3、 指针算术运算
(指针加、减一个整数)
例如,有如下定义:
long int *p2;
short score[10]
={84,65,77,60,88,86,92,93,70,66};
p2=( long int *) &score[0];
1996
1998
2000 84
2002 65
2004 77
2006 60
2008 88
2010 86
2012 92
2014 93
2016 70
2018 66
2020
p2
p2+1
p2-1
p2++; p2的值为?
p2--; p2的值为?
2004
1996
因为:*p2是long类型的,占4字节。
UNIT ELEVEN
3.3、 指针算术运算
(指针加、减一个整数)
#include <stdio.h>
#include <stdlib.h>
int main()
{
long int *p2;
short score[10]={84,65,77,60,88,86,92,93,70,66};
p2=( long int *) &score[0];
printf("%p,%p,%pn",score,p2,p2+1);
system("PAUSE");
return 0;
}
UNIT ELEVEN
3.3、 指针算术运算
(两个指针的减法)
p1、p2必须是同类型的指针变量;
结果为整数:p1和p2指向的对象之间间隔的数据个数;
p1、p2通常指向同一个数组空间。
p1 – p2
UNIT ELEVEN
3.3、 指针算术运算
(两个指针的减法)
例如,有如下定义:
short int *p1 , *p2;
short score[10]
={84,65,77,60,88,86,92,93,70,66};
p1=&score[0];
p2=score + 4 ;
1998
2000 84
2002 65
2004 77
2006 60
2008 88
2010 86
2012 92
2014 93
2016 70
2018 66
2020
p1
p2
p2 – p1 结果为4
UNIT ELEVEN
3.3、 指针算术运算
(两个指针的减法)
例如,有如下定义:
long int *p3 , *p4;
short score[10]
={84,65,77,60,88,86,92,93,70,66};
p3=( long int *) &score[0];
p4=( long int *) (score+4);
1996
1998
2000 84
2002 65
2004 77
2006 60
2008 88
2010 86
2012 92
2014 93
2016 70
2018 66
2020
p3
p4
p4 – p3 结果为2
因为:*p3、*p4是long类型的,占4字节。
UNIT ELEVEN
3.3、 指针算术运算
(两个指针的减法)
#include <stdio.h>
#include <stdlib.h>
int main()
{
long int *p3 , *p4;
short score[10]={84,65,77,60,88,86,92,93,70,66};
p3=( long int *) &score[0] ;
p4=( long int *)(score+4);
printf("%dn",p4-p3);
system("PAUSE");
return 0;
}
UNIT ELEVEN
3.4、 指针比较
若p1和p2指向同一数组,则:
p1<p2 表示p1指的元素在前;
p1>p2 表示p1指的元素在后;
p1==p2 表示p1与p2指向同一元素。
若p1与p2不指向同一数组,比较无意义;
p==NULL或p!=NULL
UNIT ELEVEN
例题8-3 堆栈(stack)是一种先进后出(first-in last-out)的
表,好比将若干个盘子堆放起来,每次放或者取一个盘子,
最先堆放的盘子最后被取走,将一个数据压入堆栈称为入栈,
从堆栈中取走一个数据称为出栈操作。现在编程实现该算法。
教材第224~226页
p1
……
stack[0]
stack[1]
stack[2]
10
p1
3
p1
push(10)
push(3)
pop()
pop()
UNIT ELEVEN
/*堆栈操作,输入0执行出栈操作,-1停止程序运行。源
程序:LT8-3.C*/
#include <stdio.h>
#include <stdlib.h>
#define SIZE 50
void push(int i); /*入栈函数使用说明*/
int pop(void); /*出栈函数使用说明*/
int *tos,*p1,stack[SIZE]; /*堆栈、栈顶及栈底指针定义*/
int main(void)
{
int value;
UNIT ELEVEN
tos=stack;
p1=stack;
do
{
printf("输入一个整数:");
scanf("%d",&value);
if (value!=0) push(value);
else printf("出栈数据是%dn",pop());
}while(value!=-1);
system("PAUSE");
return 0;
} /*end main*/
UNIT ELEVEN
/*将入栈操作定义成用户自定义函数*/
void push(int i)
{
p1++;
if(p1==(tos+SIZE))
{ /*判断堆栈是否已满*/
printf("堆栈已满n");
system("PAUSE");
exit(1);
}
*p1=i;
} /*end push*/
UNIT ELEVEN
/*将出栈操作定义成自定义函数*/
int pop(void)
{
if(p1==tos)
{ /*判断堆栈是否空*/
printf("堆栈空n");
system("PAUSE");
exit(1);
}
p1--;
return *(p1+1);
} /*end pop*/
UNIT ELEVEN
4、地址参数
UNIT ELEVEN
4.1、 一个错误的范例
(希望函数带出多个结果)
例题8-4 交换两个整数值的错误范例。教材第227页
/*数据交换错误示范,源文件:LT8-4.c*/
#include <stdio.h>
#include <stdlib.h>
void swapNumbers(int variableOne,int variableTwo);
int main(void)
{
int firstNum =0,secondNum=0;
printf("请输入两个整数:");
scanf("%d%d",&firstNum,&secondNum);
UNIT ELEVEN
4.1、 一个错误的范例
(希望函数带出多个结果)
printf("firstNum is:%dnsecondNum"
"is:%dn",firstNum,secondNum );
printf("交换两个数 n");
swapNumbers(firstNum, secondNum);
printf(" firstNum is:%dnsecondNum"
"is:%dn",firstNum,secondNum);
system("PAUSE");
return 0;
} /*end main*/
UNIT ELEVEN
4.1、 一个错误的范例
(希望函数带出多个结果)
/*函数swapNumbers:希望交换两个参数的值*/
void swapNumbers(int variableOne,int variableTwo)
{
int temp = 0; /*用于交换的临时变量*/
temp =variableOne;
variableOne =variableTwo;
variableTwo = temp;
}
UNIT ELEVEN
4.1、 一个错误的范例
(希望函数带出多个结果:原因分析)
/*函数swapNumbers:希望交换两个参数的值*/
void swapNumbers(int variableOne,int variableTwo)
{
int temp = 0; /*用于交换的临时变量
*/
temp =variableOne;
variableOne =variableTwo;
variableTwo = temp;
}
swapNumbers(firstNum, secondNum);
2000
2002
2004
2006
2008
2010
2012
firstNum
secondNum
variableOne
variableTwo
23
45
23
45
开始调用时:
UNIT ELEVEN
4.1、 一个错误的范例
(希望函数带出多个结果:原因分析)
/*函数swapNumbers:希望交换两个参数的值*/
void swapNumbers(int variableOne,int variableTwo)
{
int temp = 0; /*用于交换的临时变量
*/
temp =variableOne;
variableOne =variableTwo;
variableTwo = temp;
}
swapNumbers(firstNum, secondNum);
2000
2002
2004
2006
2008
2010
2012
firstNum
secondNum
variableOne
variableTwo
23
45
23
45
23
45
调用过程中:
UNIT ELEVEN
4.1、 一个错误的范例
(希望函数带出多个结果:原因分析)
/*函数swapNumbers:希望交换两个参数的值*/
void swapNumbers(int variableOne,int variableTwo)
{
int temp = 0; /*用于交换的临时变量
*/
temp =variableOne;
variableOne =variableTwo;
variableTwo = temp;
}
swapNumbers(firstNum, secondNum);
2000
2002
2004
2006
2008
2010
2012
firstNum
secondNum
variableOne
variableTwo
23
45
45
23
调用结束时:
UNIT ELEVEN
4.1、 一个错误的范例
(希望函数带出多个结果:原因分析)
 主调函数只能直接访问实参变量(firstNum, secondNum);
 被调函数只能直接访问形参变量,不能直接访问实参变量。
UNIT ELEVEN
4.2、 地址参数模拟引用传递
C语言中实参和形参之
间的传递的唯一方式!
形式参数
实在参数
按值传递
形式参数
实在参数
双向传递
C语言中通过指针类型
的形参模拟实现引用
调用,实现双向传递!
UNIT ELEVEN
4.2、 地址参数模拟引用传递
将形参变量
的类型从int
改为 int *
UNIT ELEVEN
4.2、 地址参数模拟引用传递
1. 主调函数:定义变元变量,通过变量名直接访问该变
元,把传入给被调用函数的数据赋值给该变量;
2. 调用被调函数:把变元的地址传递给形参;
3. 值传递:通过实参和形参之间的值传递,被调函数获
取变元的地址;
4. 间接访问变元:被调函数通过形参获得的变元地址间
接访问该变元,把计算结果赋值给该变元;
5. 调用结束:返回主调函数,释放形参内存;
6. 主调函数访问该变元,获取计算结果。
UNIT ELEVEN
/*函数swapNumbers:交换两个参数的值*/
void swapNumbers( int *variableOne, int *
variableTwo)
{
int temp = 0; /*用于交换的临时变量*/
temp = *variableOne;
*variableOne = *variableTwo;
*variableTwo = temp;
}
swapNumbers(&firstNum, &secondNum);
2000
2002
2004
2006
2008
2010
2012
firstNum
secondNum
variableOne
variableTwo
23
45
2000
2002
开始调用时:
4.2、 地址参数模拟引用传递
UNIT ELEVEN
4.2、 地址参数模拟引用传递
/*函数swapNumbers:交换两个参数的值*/
void swapNumbers(int *variableOne,int *
variableTwo)
{
int temp = 0; /*用于交换的临时变量*/
temp = *variableOne;
*variableOne = *variableTwo;
*variableTwo = temp;
}
swapNumbers(&firstNum, &secondNum);
2000
2002
2004
2006
2008
2010
2012
firstNum
secondNum
variableOne
variableTwo
23
45
34
45
2002
2000
调用过程中:
45
23
UNIT ELEVEN
4.2、 地址参数模拟引用传递
/*函数swapNumbers:交换两个参数的值*/
void swapNumbers(int *variableOne,int *
variableTwo)
{
int temp = 0; /*用于交换的临时变量*/
temp = *variableOne;
*variableOne = *variableTwo;
*variableTwo = temp;
}
swapNumbers(&firstNum, &secondNum);
2000
2002
2004
2006
2008
2010
2012
firstNum
secondNum
variableOne
variableTwo
45
23
2000
2002
调用结束时:
UNIT ELEVEN
4.2、 地址参数模拟引用传递
实在参数
变元的地址
变元的地址
变元
值传递 传入方式
形式参数
地址形参模拟引用传递实现“双向”
传递:
 本质上仍是值传递;
 形参和实参 “共享内存” :形参和
实参指向同一个对象。
swapNumbers(&firstNum,
&secondNum);
void swapNumbers(int
*variableOne,int *
variableTwo) ;
UNIT ELEVEN
4.3、 地址参数(范例)
例题8-5 交换两个整数值的正确范例。教材228~230页
/*数据交换,地址变量间接引用示例程序,源文件:LT8-5.c*/
#include <stdio.h>
#include <stdlib.h>
void getNumbers(int * inputOne, int * inputTwo);
void swapNumbers(int * variableOne, int * variableTwo);
int main(void)
{
int firstNum =0, secondNum=0;
UNIT ELEVEN
4.3、 地址参数(范例)
例题8-5 交换两个整数值的正确范例。
getNumbers( &firstNum,&secondNum);
printf("firstNum is : %d, n secondNum is : %d nn",
firstNum, secondNum );
printf("交换两个数 n");
swapNumbers(&firstNum,&secondNum);
printf(" firstNum is : %d, n secondNum is : %d n",
firstNum,secondNum);
system("PAUSE");
return 0;
} /*end main*/
UNIT ELEVEN
4.3、 地址参数(范例)
/*函数getNumbers:从键盘输入两个数*/
void getNumbers(int * inputOne, int * inputTwo)
{
printf("请输入两个整数:");
scanf("%d%d", inputOne, inputTwo);
} /*end getNumbers*/
UNIT ELEVEN
4.3、 地址参数(范例)
/*函数swapNumbers:交换两个变量的值*/
void swapNumbers(int * variableOne, int * variableTwo)
{
int temp = 0; /*用于交换的临时变量*/
temp = *variableOne;
*variableOne = *variableTwo;
*variableTwo = temp;
} /*end swapNumbers*/
UNIT ELEVEN
Q&A?
UNIT ELEVEN
本讲主要知识点
本章讲解的是C语言中指针最核心的概念,请熟练掌握!
 指针的含义、定义、初始化和用途;
 空指针和空类型指针;
 指针运算符和取地址运算符;
 动态分配内存库函数;
 指针常见错误:指针没有初始化就是使用了;
 指针运算:赋值、算术运算、关系运算、指针转换;
 指针 +整数d:表示向后移动d个数据(*指针)的内存
空间;
 地址模拟引用传递:实现双向传递,C程序中函数带出
多个结果的最常用的方法。
UNIT ELEVEN
课后思考与练习题
第8次课后作业,习题8第1、6题
UNIT ELEVEN
本讲上机练习要求
(上机练习8之1:一级指针)
1. 熟练掌握一级指针的定义、初始化、引用等操
作;
2. 熟练掌握指针运算符和取地址运算符的使用;
3. 熟练掌握指针运算;
4. 熟练掌握地址参数模拟引用传递实现双向传递;
5. 上机编程验证本讲课后作业的答案。

More Related Content

Similar to UNIT 11 一级指针——指针基本篇.ppt

第8章结构体与共用体
第8章结构体与共用体第8章结构体与共用体
第8章结构体与共用体
summerfeng
 
Slide08 807007748
Slide08 807007748Slide08 807007748
Slide08 807007748
Shiyao Ma
 
Windows Mobile 6 程式開發入門
Windows Mobile 6 程式開發入門Windows Mobile 6 程式開發入門
Windows Mobile 6 程式開發入門
Chui-Wen Chiu
 

Similar to UNIT 11 一级指针——指针基本篇.ppt (14)

105-2 iOS程式設計(二)
105-2 iOS程式設計(二) 105-2 iOS程式設計(二)
105-2 iOS程式設計(二)
 
getPDF.aspx
getPDF.aspxgetPDF.aspx
getPDF.aspx
 
getPDF.aspx
getPDF.aspxgetPDF.aspx
getPDF.aspx
 
認識 C++11 新標準及使用 AMP 函式庫作平行運算
認識 C++11 新標準及使用 AMP 函式庫作平行運算認識 C++11 新標準及使用 AMP 函式庫作平行運算
認識 C++11 新標準及使用 AMP 函式庫作平行運算
 
第8章结构体与共用体
第8章结构体与共用体第8章结构体与共用体
第8章结构体与共用体
 
Interactive Data Language
Interactive Data LanguageInteractive Data Language
Interactive Data Language
 
Slide08 807007748
Slide08 807007748Slide08 807007748
Slide08 807007748
 
Windows Mobile 6 程式開發入門
Windows Mobile 6 程式開發入門Windows Mobile 6 程式開發入門
Windows Mobile 6 程式開發入門
 
第1章 概论
第1章 概论第1章 概论
第1章 概论
 
系統程式 -- 第 11 章 嵌入式系統
系統程式 -- 第 11 章 嵌入式系統系統程式 -- 第 11 章 嵌入式系統
系統程式 -- 第 11 章 嵌入式系統
 
Arduino應用系統設計 - Arduino程式快速入門
Arduino應用系統設計 - Arduino程式快速入門Arduino應用系統設計 - Arduino程式快速入門
Arduino應用系統設計 - Arduino程式快速入門
 
第5章数组
第5章数组第5章数组
第5章数组
 
Go语言: 互联网时代的C
Go语言: 互联网时代的CGo语言: 互联网时代的C
Go语言: 互联网时代的C
 
领域驱动设计与模型驱动开发
领域驱动设计与模型驱动开发领域驱动设计与模型驱动开发
领域驱动设计与模型驱动开发
 

UNIT 11 一级指针——指针基本篇.ppt