More Related Content Similar to UNIT 11 一级指针——指针基本篇.ppt (14) UNIT 11 一级指针——指针基本篇.ppt3. UNIT ELEVEN
本讲内容提纲
1. 什么是指针
数据组织方式:指针的用途
什么是指针:直接访问和间接访问
定义指针变量
2. 指针变量的初始化
指针运算符
空指针和空类型指针
动态分配内存
指针变量的初始化
3. 指针运算
指针赋值
指针转换
指针算术运算
指针比较
4. 地址参数:指针形参模拟引用调用实现双向传递
13. UNIT ELEVEN
1.2、 指针和指针变量
指针:一个变量的地址;
指针变量:专门存放变量地址的变量。
…...
…...
2000
2004
2006
2005
整型变量count
17
变量countptr
2001
2002
2003
2000
指针
指针变量
变量的内容
变量的地址
14. UNIT ELEVEN
1.2、 指针和指针变量
指针:一个变量的地址;
指针变量:专门存放变量地址的变量。
指针变量
变量
变量地址(指针)
变量值
指向 地址存入
指针变量
…...
…...
2000
2004
2006
2005
整型变量count
17
变量countptr
2001
2002
2003
2000
15. UNIT ELEVEN
1.3、 直接访问和间接访问
直接访问:按变量名直接存取变量值
间接访问:通过存放变量地址的变量去访问变量
17
count
变量count
直接引用数
据值17
直接访问
17
count
countptr
间接访问
指针countptr间
接引用数据值17
16. UNIT ELEVEN
1.3、 直接访问和间接访问
直接访问:按变量名直接存取变量值
间接访问:通过存放变量地址的变量去访问变量
例 count=3; 直接访问
指针变量
…...
…...
2000
2004
2006
2005
整型变量count
17
变量countptr
2001
2002
2003
2000
例 *countptr=20; 间接访问
3
20
17. UNIT ELEVEN
1.4、 定义指针变量
type *name
name:指针变量名称;
*:指针变量的标志;
type:指针变量指向对象的数据类型;
type *:地址本没有类型,C语言规定type *为指针变量
name的数据类型
17
count
countptr
int count , *countptr;
countptr = &count;
*countptr = 17 ;
*countptr
18. UNIT ELEVEN
1.4、 定义指针变量
type *name
name:指针变量;
*name:指针变量name指向的对象;
定义的是指针变量name;
没有定义指针指向的对象,*name.
17
count
countptr
int count , *countptr;
countptr = &count;
*countptr = 17 ;
*countptr
19. UNIT ELEVEN
1.4、 定义指针变量(使用要点)
type *name
name:指针变量,编译系统自动分配;
*name:指针变量指向的对象,编译系统不会自动分配。
指针变量在使用前必须初始化:确保指针变量指向明确
的、合法的对象。
count
countptr
int count , *countptr;
*countptr = 17 ;
×越界使用内存
?
22. 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*/
23. 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*/
24. 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*/
27. UNIT ELEVEN
2.3、 空类型指针
空类型指针:void *
void *p;
表示不指定p是指向哪一种类型数据的指针变量;
空类型指针用于表示指针指向对象的类型未知。当内
存的语义不清楚时,空类型指针常用来表示原始内存。
使用时需要强制类型转换。
例 char *p1;
void *p2;
……
p1=(char *)p2;
p2=(void *)p1;
29. UNIT ELEVEN
2.4、 动态分配内存
(分配整块存储空间)
void *malloc( size_t size);
stdlib.h头文件中定义;
size_t:本地系统使用的无符号整型类型;通常被定义
为uinsigned int或者unsigned long;
功能:在堆中分配一个size字节的连续内存空间;
函数的返回值:所分配存储区域的起始地址。如没有足
够的存储空间分配,则返回0(记为NULL)值。
35. UNIT ELEVEN
2.4、 动态分配内存
(调整动态存储空间)
void *realloc( void * ptr, size_t size );
ptr: 是已经由malloc或calloc函数分配的存储区的指针;
size: 是重新分配的存储区的大小(字节数);
新存储区包含着和旧存储区相同的内容,如果新存储
区较大,则新增加的部分未被初始化。
返回值:是新存储区的首地址;如果没有足够的内存
空间则返回NULL,此时旧存储区内容不变。
36. 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 ));
37. UNIT ELEVEN
2.5、 指针变量初始化
type *name = initialization;
不要使用未初始化的指针变量:
全局/静态指针变量未初始化,系统自动初始化为NULL,此
时指向对象不存在;
自动指针变量未初始化,原来存储在内存空间中数据被保留;
此时指针指向的对象没有意义。
initialization:
NULL:不指向任何对象
已经定义的地址或指针;
动态分配内存。
39. 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");
43. UNIT ELEVEN
3.1、 指针赋值
ptr1 = ptr2
ptr1:指针变量;
ptr2:指针变量或者地址表达式;
限制:ptr1和ptr2两者数据类型必须相同。
int a,*aptr1,*aptr2;
aptr1=&a;
aptr2=aptr1;
/*aptr1、aptr2都指向指针变量a。*/
44. UNIT ELEVEN
3.1、 指针赋值
ptr1 = ptr2
同类型的指针可相互赋值;
任何类型的指针都可赋给空类型指针(void *);
空类型指针(void *指针)和空指针(NULL)可以直
接赋给任何类型的指针变量;
可以将一个类型的指针赋给另一种类型的指针,但这
涉及到指针转换的问题。
赋值运算符需要将右侧的指针强制转换为左侧的指针
类型之后,才能完成赋值运算。
46. 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类
型的空间
48. 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
49. 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字节。
50. 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;
}
52. 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
53. 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字节。
54. 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;
}
56. 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()
62. 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);
71. UNIT ELEVEN
4.2、 地址参数模拟引用传递
1. 主调函数:定义变元变量,通过变量名直接访问该变
元,把传入给被调用函数的数据赋值给该变量;
2. 调用被调函数:把变元的地址传递给形参;
3. 值传递:通过实参和形参之间的值传递,被调函数获
取变元的地址;
4. 间接访问变元:被调函数通过形参获得的变元地址间
接访问该变元,把计算结果赋值给该变元;
5. 调用结束:返回主调函数,释放形参内存;
6. 主调函数访问该变元,获取计算结果。
72. 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、 地址参数模拟引用传递
73. 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
74. 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
调用结束时:
76. 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;
77. 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*/