
九章针ppt课件.ppt
111页C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 第九章第九章 指指 针针本章要点:本章要点:Ø了解地址与指针的概念了解地址与指针的概念Ø熟练掌握指针变量的定义、初始化及指针的运算熟练掌握指针变量的定义、初始化及指针的运算 Ø掌握指针与数组、指针数组、二级指针等知识掌握指针与数组、指针数组、二级指针等知识 Ø熟练掌握字符串的指针与指向字符串的指针变量熟练掌握字符串的指针与指向字符串的指针变量Ø了解指针与函数的概念了解指针与函数的概念 Ø掌握指针作为函数参数的应用掌握指针作为函数参数的应用Ø了解多维数组指针的概念了解多维数组指针的概念 C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 指针指针是是C C语言中最重要的组成部分利语言中最重要的组成部分利用用指针指针可以表示可以表示 复杂的数据结构;动态分复杂的数据结构;动态分配内存;灵活处理字符串和数组;直接处配内存;灵活处理字符串和数组;直接处理内存地址;理内存地址; 从函数调用中获取多个值等从函数调用中获取多个值等C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院对变量值的存取实质上是通过对变量值的存取实质上是通过地址地址进行的。
进行的示意图示意图9.1 指针的概念指针的概念 C 语言中,任何一个语言中,任何一个变量名变量名实质上都代表着内实质上都代表着内存中的某一个存储单元,每一个存储单元都有一个存中的某一个存储单元,每一个存储单元都有一个地址地址C系统能自动将系统能自动将变量名变量名和它的和它的地址地址联系起来联系起来变量定义及内存分配实例变量定义及内存分配实例对变量的两种访问方式:对变量的两种访问方式:直接访问直接访问 和和 间接访问间接访问 int i , j , k ; i = 3 ; j = 6 ; k = 9 ;则编译时系统分别为则编译时系统分别为 i , j , k 各分配各分配 2 个字节个字节 如如: 2000 , 2001 i 2002 , 2003 j 2004 , 2005 k例例例例图图图图 内存用户数据区内存用户数据区36920002000200220043010 …… …… 变量变量 i变量变量 j变量变量 k变量变量 i_ pointer 如如: int i = 3 ; printf ( “ %d ” , i ) ; 执行是执行是: 根据变量名根据变量名 i 找到找到 i 的地址的地址 ( 如如: 2000 ),然后,然后 从地址从地址 2000 开始的两开始的两个字节中取出数据个字节中取出数据(即变量的值即变量的值 3 ), 再将再将其输出。
这种据变量名按变量地址存取变其输出这种据变量名按变量地址存取变量的值的量的值的 方式叫方式叫 “ 直接访问直接访问 ”方式 说明说明说明说明重点重点重点重点 2000i3 int i = 3 ; 表示将表示将 3 送送到变量到变量i 所占的内存单元中所占的内存单元中重点重点重点重点 C 语言允许定义和使用一种特殊的变量,语言允许定义和使用一种特殊的变量,这种变量专门用于存放其它变量的这种变量专门用于存放其它变量的地址地址如前面的变量面的变量 i_ pointer 如 果把变量果把变量 i 的地址赋的地址赋给给i_ pointer ,, 即即 i_ pointer = &i这 样就样就可以通过变量可以通过变量 i_ pointer 获取变量获取变量 i 的地址,的地址, 然后再然后再 取出取出 i 的值这种方式叫的值这种方式叫 “间接访问间接访问”方式 如图所示如图所示: 2000 2000i_pointer3 将将3送到变量送到变量 i_pointer 所所指向指向 的内存单元中的内存单元中iC语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 指针指针: : 一个变量的一个变量的地址地址叫该变量的叫该变量的 “ “ 指针指针 ” ”。
指针变量指针变量: : 用于存放其它变量的用于存放其它变量的地址地址的变量 指向指向: :如如 i_pointeri_pointer= &i= &i ,,就称就称i_pointeri_pointer指向变量指向变量i i 目标变量目标变量: : 指针变量所指向的变量指针变量所指向的变量有关指针的几个概念:有关指针的几个概念:C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 说明说明: 1. 类型说明符类型说明符表示指针变量所指向的变量的类型,表示指针变量所指向的变量的类型,同类型变量的地址才能放到指向该类型变量的指针同类型变量的地址才能放到指向该类型变量的指针变量中例如例如2. 不能把一个不能把一个整型量整型量或任何其它或任何其它非地址非地址类型的数据类型的数据赋给一个指针变量赋给一个指针变量例如例如示例一示例一 实例二实例二9.2 变量的变量的指针指针和指向变量的和指向变量的指针变量指针变量一、指针变量的定义一、指针变量的定义格式格式: 类型说明符类型说明符 *标识符标识符如:如: int *pointer_1 , *pointer_2 ; float *fp1 , *fp2 ;例例例例例例例例&i&jpointer_1pointer_2 i j如如: int i , j , *pointer_1 , *pointer_2 ; 若若: pointer_1 = &i ; pointer_2 = &j ; 则则:flaot f1 ; int *p ; p = &f1 ; ( 不正确不正确 )例例例例如如: int *p ; p = 100 ; (不合法不合法) 但但: p = NULL 或或 p = 0 或或 p = ‘\0’ 则是合法则是合法 的,都表示为指的,都表示为指针赋了针赋了“空值空值”。
这并不意味着这并不意味着 p 指指向向 地址为地址为0 的单元,而是不指向的单元,而是不指向任何单元,但任何单元,但 p 中有确定的值中有确定的值例例例例C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院二、指针变量的引用二、指针变量的引用 例例 9.1 main ( ) { int a , b ; int *p1 , *p2 ; a = 100 ; b = 10 ; p1 = &a ; p2 = &b ; printf ( “ %d , %d \n ”, a , b ) ; printf ( “ %d , %d \n ”, *p1 , *p2 ) ; } 结果结果: 100 , 10 100 , 10 &a&b10010p1p2 a b*p1*p2“直接访问直接访问”方方式式“间接访问间接访问”方方式式C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 关于关于 & 与与 * 运算符的说明运算符的说明: 1: & 是取地址运算符。
是取地址运算符 例如例如 2. & , * , + + , – – 同优先级,同优先级, 按从按从右至左方右至左方向结合 示例示例1 示例示例2 示例示例3 如如: int a , *p1 , *p2 ; p1 = &a ; 则则: &*p1 与与 &a 等效等效p2 = &*p1 ; 或或 p2 = &a ; 则则: p2 也指向变量也指向变量 a例子例子例子例子如如: &a , &b 等 * 是指针运算符是指针运算符 用于定义时用于定义时表示其后的表示其后的标识符标识符是是指针变量指针变量而在程序中在程序中*p 则表示指针变量则表示指针变量 p 所指所指向的变量,即向的变量,即目标变量目标变量例子例子例子例子例子例子例子例子 如如: int a , *p1 ; p1 = &a ; 则则: *&a 与与 *p1 等效,即等价于变量等效,即等价于变量 a 。
&ap1*p1*&a a如如: int a , *p1 ; p1 = &a ; 则则: (*p1) + + 等价于等价于 a + + 但注意但注意 *p1+ + 不等价于不等价于 (*p1) + + 因为因为 *p1+ + 等价于等价于 *( p1+ + ) 即先得即先得 p1 所指向变量的所指向变量的值值,再使指针变量,再使指针变量 p1的值自增的值自增例子例子例子例子C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 例例 9.2 main ( ) { int *p1 , *p2 , *p , a , b ; scanf ( “ %d , %d ” , &a , &b ) ; p1 = &a ; p2 = &b ; if ( a < b ) { p = p1 ; p1 = p2 ; p2 = p ; } printf ( “ a = %d , b = %d \n”, a , b ) ; printf ( “ max = %d , min = %d \n ”, *p1 , *p2 ) ; } 如输入如输入: 5 , 9 输出输出: a = 5 , b = 9 max = 9 , min = 5 数据指针交换示意图数据指针交换示意图 注意事项注意事项进行地址交换进行地址交换 本程序是采用交换变量本程序是采用交换变量 a 和和 b 的地址来实现两个数的地址来实现两个数的比较的。
且比较前后的比较的且比较前后 a , b 的值并未发生变化的值并未发生变化重点重点重点重点重点重点重点重点&a&b59&b&a95p1p2p pp1p2aba b交换前交换前交换后交换后C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院三、三、 指针变量作为函数的参数指针变量作为函数的参数 函数调用时,把实际参数的值传递给形式参数函数调用时,把实际参数的值传递给形式参数 指针变量可以作实际参数,其作用也是将实际参数指针变量可以作实际参数,其作用也是将实际参数的值传递给形式参数,这个时候的值代表是将一个变的值传递给形式参数,这个时候的值代表是将一个变量的量的地址,地址,把把地址地址传送给被调函数的形式参数传送给被调函数的形式参数C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 例例 9.3 swap ( int *p1 , int *p2 ) { int p ; p = *p1 ; *p1 = *p2 ; *p2 = p ; } main ( ) { int a , b , *pointer_1 , *pointer_2 ; scanf ( “ %d , %d ” , &a , &b ) ; pointer_1 = &a ; pointer_2 = &b ; if ( a < b ) swap ( pointer_1 , pointer_2 ) ; printf ( “ \n %d , %d \n ”, a , b ) ; }交换目标变量,即值的交换交换目标变量,即值的交换C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 若输入若输入: 5 , 9 输出为输出为: 9 , 5&a&b59abpointer_1pointer_2&a&b&a&b59abp1p2pointer_1pointer_2&a&a&b&b95p1pointer_1p2pointer_2ab&a&b95abpointer_1pointer_2(a)(b)(c)(d)本程序采用的是交换本程序采用的是交换 a 和和 b 的的值值,,而而 p1和和 p2 的值不变。
的值不变 同同例例9.2相反相反.C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 如果把如果把 swap 函数改成函数改成 : swap (int *p1 , int *p2 ) { int *p ; *p = *p1 ; *p1 = *p2 ; *p2 = *p ; } 此句有问此句有问题题C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 swap ( int x , int y ) { int t ; t = x ; x = y ; y = t ; }55995995abxya bxy(a) (b) main ( ) { int a , b ; scanf (“ %d , %d ” , &a , &b ) ; if ( a < b ) swap ( a , b ) ; printf ( “ \n %d , %d \n ”, a , b ) ; }C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院说明说明: 1. 如想通过函数调用得到如想通过函数调用得到 n 个要改变的值。
个要改变的值 (1) 在主调函数中设在主调函数中设 n 个变量,并用个变量,并用 n 个指针变量个指针变量 指向它们指向它们 (2) 将指针变量作将指针变量作实参实参,使,使 n 个变量的个变量的地址地址传给所传给所 调用的函数调用的函数形参形参 (3) 通过形参指针变量,改变该通过形参指针变量,改变该 n 个变量的个变量的值值 (4) 主调函数中就可以使用这些改变了值的变量主调函数中就可以使用这些改变了值的变量 2. 不能通过改变形参指针变量不能通过改变形参指针变量本身的值本身的值而使而使实参指实参指 针变量的值针变量的值改变 &ap1&aq1函数调用时函数调用时&bq1在被调函数中在被调函数中C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 3. 可以通过改变形参指针变量所可以通过改变形参指针变量所指向指向的变量的值来改的变量的值来改 变实参指针变量所变实参指针变量所指向指向的变量的值。
的变量的值 5 a&a p1&aq1 补例补例1:: void point ( int *q1 ) { q1 + = 2 ; } main( ) { int *p1 , a = 4 ; p1= &a ; point ( p1 ) ; printf ( “ %d \n” , *p1 ) ; }C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 4 a&a p1&aq1 补例补例2:: void point ( int *q1 ) { *q1 + = 2 ; } main( ) { int *p1 , a = 4 ; p1= &a ; point ( p1 ) ; printf ( “ %d \n” , *p1 ) ; }C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 swap (int *p1 , int *p2 ) { int *p ; p = p1 ; p1 = p2 ; p2 = p ; } main ( ) { int a , b , *pointer_1 , *pointer_2 ; scanf ( “ %d , %d ” , &a , &b ) ; pointer_1 = &a ; pointer_2 = &b ; if ( a < b ) swap ( pointer_1 , pointer_2 ) ; printf ( “ \n %d , %d \n ”, a , b ) ; }本函数中试图通过改变本函数中试图通过改变形参指针变形参指针变量量的值来使的值来使实参指针变量实参指针变量的值改变的值改变C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院a&a&b59bpointer_1pointer_2(a) &a&b59abp1p2(b) &b&a59abp1p2(c) a&b&a59bpointer_1pointer_2(d) &a&b59abpointer_1pointer_2(d) C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 exchange ( int *q1 , int *q2 , int *q3 ) { if (*q1 < *q2) swap ( q1 , q2 ) ; if (*q1 < *q3) swap ( q1 , q3 ) ; if (*q2 < *q3) swap ( q2 , q3 ) ; }例例 9.4 swap ( int *pt1 , int *pt2 ) { int p ; p = *pt1 ; *pt1 = *pt2 ; *pt2 = p ; }C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院main ( ) { int a , b , c , *p1 , *p2 , *p3 ; scanf ( “ %d , %d , %d ”, &a , &b , &c) ; p1 = &a ; p2 = &b ; p3 = &c ; exchange ( p1 , p2 , p3 ) ; printf ( “ \n%d, %d, %d\n ”, a , b , c ) ; } 运行如下运行如下: 9 , 0 , 10 : 9 , 0 , 10 10 , 9 , 0 10 , 9 , 0C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院9010p1 a b cp2 p3 9010q1 b cq2 q3 a exchange90pt1 bpt2 a swapp1q1 p1C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 9.3 9.3 数组的指针和指向数组的指针变量数组的指针和指向数组的指针变量 C C 语言中,指针变量可以指向变量,也可以指向语言中,指针变量可以指向变量,也可以指向数组数组和和数组元素数组元素。
数组的指针数组的指针: : 数组的数组的起始地址起始地址( ( 首地址首地址 ) ) 数组元素的指针数组元素的指针: : 数组元素的地址数组元素的地址C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 一、指向一维数组的指针变量的定义与赋值一、指向一维数组的指针变量的定义与赋值 指向数组的指针变量的定义同指向变量的指针变量的指向数组的指针变量的定义同指向变量的指针变量的 定义相同定义相同 如如: int a[10] ; int *p ; 若若: p = &a[0] ; 则则 p 指向了指向了a 数组的第数组的第 0 号元素 由于数组名代表数组的由于数组名代表数组的首地址首地址(即即起始地址起始地址),, 故故: p = &a[0] ; 等价于等价于 p = a ; 也可也可: int a[10] ; int *p = &a[0] ; int *p = a ; 注意注意 int *p = &a[0] ; 的含义是将数组的的含义是将数组的首地址首地址赋给赋给指针变量指针变量 p ,,而不是赋给而不是赋给 ( *p ) 。
C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院二、二、 通过指针引用数组元素通过指针引用数组元素 如如: int a[10] , *p ; p = a ; 则则: (1) p a[0]的地址的地址 p + 1 a[1]的地址的地址 p + i a[i]的地址的地址 (2) *p ==a[0] , *(p +1) = =a[1] , … *(p +i) = = a[i]说明说明: 1. 数组元素在内存中是连续存放的,数组元素在内存中是连续存放的, C 语言规定,语言规定, 指针变量指针变量 p + 1 指向下一个元素指向下一个元素 (不不是简单的加是简单的加 1 ) 如数组元素为实型,如数组元素为实型, 则则 p + 1 所表示的实所表示的实际地址是际地址是 p + 1 d = p + 1 4 ( d 为一个数组元素所为一个数组元素所占的字节数占的字节数)&a[0] 1 3…20 a[0]a[1]a[9]pC语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 2. ( p + i ) 表示指向表示指向 a[i] 的地址,而的地址,而 a + i 也表示也表示 a[i] 的地址,故的地址,故 程序中程序中( p + i ) 等价于等价于 a + i 。
如如: p + 2 ; a + 2 ; 3. 指向数组的指针变量可以带下标指向数组的指针变量可以带下标 如如: p[i] *( p +i ) 综上所述综上所述: 数组元素的引用可以数组元素的引用可以: (1) 下标法下标法: 数组名数组名[下标下标] 或或 指针变量名指针变量名[下标下标] (2) 指针法指针法: *(p +i) 或或 *(a +i) (假定假定: int a[10] , *p = a ; )a数组数组 p p+1, a+1 p+i , a+i p+9 , a+9 a[0] a[1] a[i] a[9] *(p +i)C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 例例 9.5 用三种方法输出数组各元素用三种方法输出数组各元素 (1)下标法下标法 main ( ) { int a[10] , i ; for ( i = 0 ; i < 10 ; i + + ) scanf ( “ %d ”, &a[i] ) ; printf ( “ \n” ) ; for ( i = 0 ; i < 10 ; i + + ) printf ( “%d ”, a[i] ) ; }C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 (2)用数组名计算元素地址用数组名计算元素地址 main ( ) { int a[10] , i ; for ( i = 0 ; i < 10 ; i + + ) scanf ( “ %d ”, &a[i] ) ; printf ( “ \n” ) ; for ( i = 0 ; i < 10 ; i + + ) printf ( “%d ”, *( a +i ) ) ; }C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院(3) 用指针变量指向数组元素用指针变量指向数组元素 main ( ) { int a[10] , i , *p ; for ( i = 0 ; i < 10 ; i + + ) scanf ( “ %d ”, &a[i] ) ; printf ( “ \n” ) ; for ( p = a ; p < (a +10) ; p + + ) printf ( “%d ”, *p ) ; }C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院注意几点注意几点: : (1)(1) 指针变量可以作自增,自减运算。
指针变量可以作自增,自减运算 如如: : + ++ + p p , , p p – –– – 而数组名不能作自增,自减运算而数组名不能作自增,自减运算 如如: : a a + + , – – + + , – – a a 等均不合法因为等均不合法因为数组名是常量数组名是常量 (2)(2) 注意指针变量的当前值注意指针变量的当前值 如如: : 例例 9.69.6 C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 main ( ) { int a[10] , i , *p ; p = a ; for ( i = 0 ; i < 10 ; i + + ) scanf ( “ %d ”, p + + ) ; printf ( “ \n” ) ; for ( i = 0 ; i < 10 ; i + + , p + + ) printf ( “%d ”, *p ) ; } for( i = 0, p=a ; i < 10 ; i + +, p + +)或或 for ( p = a ; p < a +10 ; p + + )pa 数组数组C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 (3) 注意指针变量的运算注意指针变量的运算 如如: int a[10] , i , *p ; p = a ; 则则:a. p + + (或或 p + = 1 ) 表示表示 p 指向指向 a[1] ,, 此时若执行此时若执行 *p 则取出则取出 a[1] 元素的值。
元素的值 b. “*” 与与 “+ +” 同同优先级,自右往左结合优先级,自右往左结合 如如: *p + + 等效于等效于 *(p + + ) , 即先取即先取 p 所指向变量的值,所指向变量的值, 再使再使 p + 1而而 *(p + + ) 与与*(+ + p ) 的的作用不同前作用不同前 者先取者先取*p 的值,后使的值,后使p + 1 ; 后者是先使后者是先使 p + 1 ,,再再 取取 *p 的值的值 c. (*p) + + 表示使目标变量的值加表示使目标变量的值加 1 而不是指针变而不是指针变 量的值加量的值加 1d. *(p + + ) 等价等价于于 a[i + +] *(+ + p ) 等价等价于于 a[+ + i] 即先使即先使 p 自增自增,再作再作 * 运算C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 如如: main ( ) { int a[100] , *p ; p = a ; while ( p < a +100 ) printf ( “ %d ”, *p + + ) ; } main ( ) { int a[100] , *p ; p = a ; while ( p < a +100 ) { printf ( “ %d ”, *p ) ; p + + ; } }C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院三、 数组名作函数参数 数组名作函数参数时,实际上是将实参数组的首地址 传给形参。
这样实参数组与形参数组共占同一段内存 使得在调用函数过程中,形参数组中元素值发生变化也 就使实参数组的元素值随之而发生变化C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 main ( ) f ( int arr[ ] , int n ) { int array[10] ; { …… f ( array , 10 ) ; …… …… } }arrayarrC语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 void inv ( int x[ ] , int n ) { int t , i , j , m = (n – 1) /2 ; for ( i = 0 ; i < = m ; i + + ) { j = n – 1 – i ; t = x[i] ; x[i] = x[j] ; x[j] = t ; } return ; }可可去掉去掉 3 7 9 11 0 6 7 5 4 2 2 4 5 7 6 0 11 9 7 3imj 例例 9.7 将数组将数组 a 中中 n 个整数按相个整数按相反顺序反顺序存放。
存放 即将即将第一第一个元素和个元素和最后最后一个元素对换,将第二个同倒一个元素对换,将第二个同倒 数第二个对换数第二个对换. …….即两两对换,直到即两两对换,直到: a[(n – 1) /2] 与与 a[ n – ( n – 1 ) / 2 – 1 ] 对换为止对换为止 C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 void main ( ) { static int i , a[10] = { 3 ,7 ,9 ,11 ,0 ,6 ,7 ,5 , 4 , 2 } ; printf ( “ The original array : \n ” ) ; for ( i = 0 ; i < 10 ; i + + ) printf ( “ %d , ”, a[i] ) ; printf ( “ \n ” ) ; inv ( a , 10 ) ; printf ( “ The array has been inverted : \n ” ) ; for ( i = 0 ; i < 10 ; i + + ) printf ( “ %d , ”, a[i] ) ; printf ( “ \n ” ) ; }运行结果运行结果: The original array : 3 , 7 , 9 , 11 , 0 , 6 , 7 , 5 , 4 , 2 The array has been inverted : 2 , 4 , 5 , 7 , 6 , 0 , 11 , 9 , 7 , 3 C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 以上程序也可以改为如下以上程序也可以改为如下:void inv ( int *x , int n ){ int *p , t , *i , *j , m = (n – 1) /2 ; i = x ; j = x + n – 1 ; p = x + m ; for ( ; i < = p ; i + + , j – – ) { t = *i ; *i = *j ; *j = t ; } return ; }a 数组数组 a[0] a[1] ….. a[9]3 7 0 i , x p = x+m j 2 4 5 7 6 11 9C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院main ( ){ static int i , a[10] = { 3, 7, 9, 11, 0, 6, 7, 5 , 4 , 2 } ; printf ( “ The original array : \n ” ) ; for ( i = 0 ; i < 10 ; i + + ) printf ( “ %d ”, a[i] ) ; printf ( “ \n ” ) ; inv ( a , 10 ) ; printf ( “ The array has been inverted : \n ” ) ; for ( i = 0 ; i < 10 ; i + + ) printf ( “ %d ”, a[i] ) ; printf ( “ \n ” ) ; } C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 int max , min ; void max_min_value ( int array[ ] , int n ) { int *p , *array_end ; array_end = array + n ; max = min = *array ; for ( p = array + 1 ; p < array_end ; p + + ) if (*p > max ) max = *p ; else if ( *p < min ) min = *p ; return ; }等价于等价于*(array + 0) 即即 array[0]例例 9.8 从从 10 个数中找出其中最大值和最小值个数中找出其中最大值和最小值C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院void main ( ){ int i , number[10] ; printf ( “ enter 10 data \n ”) ; for ( i = 0 ; i < 10 ; i + + ) scanf ( “ %d ”, &number[i] ) ; max_min_value( number , 10 ) ; printf ( “ \n max = %d , min = %d \n ”, max , min ) ;} 运行结果运行结果: enter 10 data –2 4 6 8 0 –3 45 67 89 100 max = 100 , min = –3C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院此例也可改用指针变量来传送地址,程序可改为此例也可改用指针变量来传送地址,程序可改为:int max , min ; void max_min_value ( int *array , int n ) { int *p , *array_end ; array_end = array + n ; max = min = *array ; for ( p = array + 1 ; p < array_end ; p + + ) if (*p > max ) max = *p ; else if ( *p < min ) min = *p ; return ; } C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院void main ( ){ int i , number[10] , *p ; p = number ; printf ( “ enter 10 data \n ”) ; for ( i = 0 ; i < 10 ; i + + , p + + ) scanf ( “ %d ”, p ) ; printf ( “ the 10 data : \n ” ) ; for ( p = number , i = 0 ; i < 10 ; i + + , p + + ) printf ( “ %d ”, *p ) ; p = number ; max_min_value( p , 10 ) ; printf ( “ \n max = %d , min = %d \n ”, max , min ) ; }for ( p = number ; p < ( number +10 ) ; p + + ) 综上所述,对于实参数组想在被调函数中改变综上所述,对于实参数组想在被调函数中改变此数组元素的值,实参与形参的对应关系可以如下此数组元素的值,实参与形参的对应关系可以如下: :C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 (1) 二者都用数组名二者都用数组名 main ( ) f ( int x[ ] , int n ) { int a[10] ; { …… …… f ( a , 10 ) ; …… } } 特点特点: a 和和 x 数组共用同一段内存单元。
数组共用同一段内存单元 (2) 实参为数组名,形参用指针变量实参为数组名,形参用指针变量 main ( ) f ( int *x , int n ) { int a[10] ; { …… …… f ( a , 10 ) ; …… } }C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 (2) 实参为数组名,形参用指针变量实参为数组名,形参用指针变量 main ( ) f ( int *x , int n ) { int a[10] ; { …… …… f ( a , 10 ) ; …… } }特点特点: 实参将数组的首地址传给形参指针变量,通过指实参将数组的首地址传给形参指针变量,通过指 针变量指向数组中的任一元素针变量指向数组中的任一元素,进而作相应的处理。
进而作相应的处理C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 (3) 二者都用指针变量二者都用指针变量 main ( ) f ( int *x , int n ) { int a[10] , *p ; { p = a ; …… …… f ( p , 10 ) ; …… } } 特点特点: 先使先使 p 指向指向 a 数组,再将数组,再将 p 传给传给 x , 使使 x 也指也指向向 a 数组,从而进行处理数组,从而进行处理C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院(4) 实参为指针变量,而形参为数组名实参为指针变量,而形参为数组名 main ( ) f ( int x[ ] , int n ) { int a[10] , *p ; { p = a ; …… …… f ( p , 10 ) ; …… } } 特点特点: 利用指针变量将利用指针变量将 a 数组的首地址传给数组的首地址传给 x 数组。
使数组使 两数组共用同一段内存单元利用两数组共用同一段内存单元利用x[i]值的变化,值的变化,使使a[i]的值也发生变化的值也发生变化 注意注意: 在上述四种处理方式中,当用指针变量作实参时,在上述四种处理方式中,当用指针变量作实参时,必须先使指针变量有确定的值,即指向一个已定必须先使指针变量有确定的值,即指向一个已定 义的数组义的数组C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 四四、、二维数组的指针和指向二维数组的指针变量二维数组的指针和指向二维数组的指针变量 1. 二维数组和数组元素的地址二维数组和数组元素的地址 C 语言中二维数组实际上是由若干个按行存放的一语言中二维数组实际上是由若干个按行存放的一维数组构成的如:维数组构成的如: int a[3][4] ;; a[0] – – a[0][0] a[0][1] a[0][2] a[0][3] a[1] – – a[1][0] a[1][1] a[1][2] a[1][3] a[2] – – a[2][0] a[2][1] a[2][2] a[2][3] a 代表首元素的地址,而此时首元素代表首元素的地址,而此时首元素a[0]又是一个包含又是一个包含有有 4个元素的一维数组。
所以个元素的一维数组所以 a (或或 a + 0 )表示二维数组表示二维数组第第0 行的地址同理:行的地址同理: a + 1 ,, a + 2 分别表示二维数组分别表示二维数组第第 1 行和第行和第 2 行的地址所以,二维数组名是一个行的地址所以,二维数组名是一个行指行指针针 a[0],,a[1],,a[2]分别表示一维数组名,所以分别表示一维数组名,所以a[0]代代表表 一维数组一维数组a[0]中第中第0列元素的地址,即列元素的地址,即 &a[0][0]aC语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院同理:同理:a[1]的值为的值为&a[1][0],, a[2]的值为的值为&a[2][0] 二维数组元素的地址可表示为:二维数组元素的地址可表示为: (1) &a[i][j] (2) a[i] + j (3) * (a + i ) + j ( 因为因为 a[i] 等价于等价于 * (a + i ) ) 二维数组元素的引用可表示为:二维数组元素的引用可表示为: (1) a[i][j] (2) * ( a[i] + j ) (3) * (* (a + i ) + j ) 2. 指向二维数组的指针变量指向二维数组的指针变量 (1) 指向二维数组的指向二维数组的列指针列指针变量变量 int a[3][4] , *p ;C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 如:如:p = a[0] ; 或或 p = &a[0][0] ; p = * ( a + 0 ) ; p = * a ; 则则 p 是一个指向二维数组是一个指向二维数组 a 第第 0 行第行第 0 列元素的指列元素的指针针 变量。
变量 即即 p 是一个是一个列指针变量列指针变量 ) 此时此时 p +1 则指向第则指向第 0 行行 第第 1 列的元素列的元素 说明:说明: 上述上述 p = a[0] ; 不能写成不能写成 p = a ; 因为尽管因为尽管 a[0] 和和 a 都表示地址且都表示地址且 值相同,但二者的值相同,但二者的地址基类型地址基类型不同 即即 a[0] 是一个是一个列地址列地址,而,而 a 是一个是一个 行地址行地址 1 3 5 7 2 4 6 81112 13 14p p +1C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 #include “ stdio.h ” void main ( ) { int a[3][4]={1, 2, 3, 4, 9, 8, 7, 6, 10, 11, 5, 2}; int *p = a[0] ; ( 或或 int *p = &a[0][0] ; ) for ( ; p < a[0] +12 ; p+ + ) { if (( p – a[0] ) %4 = = 0 ) printf( “\n”) ; printf( “%4d” , *p ) ; } } (2) 指向二维数组的指向二维数组的行指针行指针变量变量 由于二维数组是由按行存放的一维数组构成,由于二维数组是由按行存放的一维数组构成,C 语语 言中可以用言中可以用行指针变量行指针变量来引用二维数组元素。
来引用二维数组元素 C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 定义格式:定义格式: 数据类型数据类型 (* 标示符标示符 )[常量常量] 如:如: int ( *p)[4] ; 表示表示 p 所指的对象是有所指的对象是有 4 个整型元素的数组个整型元素的数组 int a[3][4] , ( *p)[4] ; 若:若:p = a ; 则则 p 是是指向指向 a 数组第数组第 0 行行的指针变量,的指针变量, 即即 p 是一个是一个行指针变量行指针变量 此时,此时,p +1则指向则指向 a 数组第数组第 1 行,行, p + i 则指向则指向 a 数组第数组第 i 行 所以,所以, *( p + i ) + j 表示表示 a 数组数组 中第中第 i 行行 j 列元素的地址列元素的地址 而而 *(*( p + i ) + j ) 则则表示表示表示表示 a 数组中第数组中第 i 行行 j 列元素的列元素的值值。
注意注意不能写成不能写成 p = a[0] 1 3 5 7 2 4 6 811 12 13 14pp+1C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 例:例: 输出二维数组任意行任意例元素的值输出二维数组任意行任意例元素的值 void main ( ) { int a[3][4]={1, 2, 3, 4, 9, 8, 7, 6, 10, 11, 5, 2}; int ( *p)[4] , i , j ; p = a ; scnaf( “ i = %d , j =%d ” , &i , &j ) ; printf( “ a[%d , %d ] =%d\n ” , i , j , *(*( p + i ) + j ) ) ; } 3. 二维数组名和指向二维数组的指针变量作函数参数二维数组名和指向二维数组的指针变量作函数参数 补充例:补充例:用用函数调用方式函数调用方式编写程序找出二维数组编写程序找出二维数组a 中每中每 行的最小值并输出。
要求:行的最小值并输出要求: (1) 二维数组元素的值用随机函数产生二维数组元素的值用随机函数产生( 0 ~ 50)之间之间 (2) 每行中元素的最小值在每行中元素的最小值在line_min( ) 函数中求出函数中求出 (3) 在主函数中输出每行的最小值在主函数中输出每行的最小值C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 void main( ) { 1、、 定义一个二维数组定义一个二维数组 2、、 调调随机函数随机函数对二维数组对二维数组 元素元素赋值赋值 3、、 调用调用 line_min 函数函数 4、、 输出结果到屏幕输出结果到屏幕 } line_min ( ) { 1、、 接收实参接收实参 2、、求二维数组每行中的最小值求二维数组每行中的最小值 }C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 方法一、方法一、用用列指针列指针来求解来求解 #include “ stdlib.h ” #define N 3 #define M 4 void main ( ) { int a[N][M] , min , i , j ; for( i = 0 ; i < N ; i + +) for( j = 0 ; j< M ; j + +) { a[i][j]= random( 50 ) ; printf( “ %4d ” , a[i][j] ) ; if(( j+1)%4 = = 0 ) printf( “\n” ) ; } for( i = 0 ; i < N ; i + +) { min = line_min( a[i] ) ; printf( “ a[%d]: min = %d \n ” , i , min ) ; } }C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 line_min ( int * p ) { int j , min ; min= *(p + 0) ; for( j = 1 ; j < M ; j + +) if ( min > *( p + j ) ) min = * ( p + j ) ; return min ; } 方法二、方法二、用用行指针行指针来求解来求解 C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 #include “ stdlib.h ” #define N 3 #define M 4 void main ( ) { int a[N][M] , min , i , j ; for( i = 0 ; i < N ; i + +) for( j = 0 ; j< M ; j + +) { a[i][j]= random( 50 ) ; printf( “ %4d ” , a[i][j] ) ; if(( j+1)%4 = = 0 ) printf( “\n” ) ; } for( i = 0 ; i < N ; i + +) { min = line_min( a + i ) ; printf( “ a[%d]: min = %d \n ” , i , min ) ; } }C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 line_min ( int (* p)[M] ) { int j , min ; min= * (*p) ; for( j = 1 ; j < M ; j + +) if ( min > * (* p + j ) ) min = * (* p + j ) ; return min ; } 说明:说明:random( x ) 函数能产生一个函数能产生一个 ( 0 ~ x – 1) 间的间的随机整数。
随机整数 相关的函数有:相关的函数有: rand( ) ,,其功能是产生其功能是产生 0 ~ 32767间的随机数间的随机数 如:如: ( rand( )%90 + 10.0 ) / 10.0 就能产生就能产生 1.0 ~ 10.0 之间的实数之间的实数 C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院§9.4 字符串的指针和指向字符串的指针变量字符串的指针和指向字符串的指针变量 字符串的指针字符串的指针就是字符串的就是字符串的首地址首地址一、一、 字符串的表示形式字符串的表示形式 1: 用字符数组实现用字符数组实现 例例 9.16 main ( ) { static char string[ ] = “ I Love China ” ; printf ( “ %s\n ” , string ) ; } 例中例中 string 是数组名,是数组名, 它表示字符数组的它表示字符数组的首地址首地址。
相应的相应的 string[i] 表示数组中的一个元素如表示数组中的一个元素如: string[4] 代表第代表第 5 个元素,即个元素,即 字母字母 v 2: 用字符指针实现用字符指针实现C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 char *string ; string = “ I Love China ” ; 或者或者: char *string = “ I Love China ” ; 其含义是将字符串的其含义是将字符串的首地址首地址赋给指针变量赋给指针变量 string 尽管没有直接定义字符型数组,但实际上尽管没有直接定义字符型数组,但实际上 C 语言对字符语言对字符串常量均按字符数组来处理即在内存中开辟了一个字符串常量均按字符数组来处理即在内存中开辟了一个字符数组用来存放字符串常量数组用来存放字符串常量 例例 9.17 main ( ) { char *string = “ I Love China ” ; printf ( “ %s\n ” , string ) ; }C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 注意注意: C 语言中对字符串可以进行整体输入和输出。
语言中对字符串可以进行整体输入和输出 而对数值型数组则不能用数组名来输出它的全部而对数值型数组则不能用数组名来输出它的全部 元素,只能逐个元素输出元素,只能逐个元素输出 对字符串的处理可以用对字符串的处理可以用下标法下标法,也可用,也可用指针法指针法 例例 9.18 将字符串将字符串 a 复制到字符串复制到字符串 b main ( ) { char a[ ] = “ I am a boy .” , b[20] ; for ( i = 0 ; *( a + i ) ! = ‘\0’ ; i + +) *( b + i ) = *( a + i ) ; *( b + i ) = ‘\0’ ; printf ( “ string a is : %s \n ”, a ) ;C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 printf ( “ string b is : ” ) ; for ( i = 0 ; b[i] ! = ‘\0’ ; i + +) printf ( “ %c ”, b[i] ) ; printf ( “ \n ” ) ; } 运行结果运行结果: string a is : I am a boy . string b is : I am a boy . 例例 9.19 用指针变量来处理例用指针变量来处理例 9.18 问题问题. main ( ) { char a[ ] = “ I am a boy .” , b[20] , *p1 , *p2 ; int i ; p1 = a ; p2 = b ; for ( ; *p1! = ‘\0’ ; p1 + + , p2 + + ) C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 *p2 = *p1 ; *p2 = ‘\0’ ; printf ( “ string a is : %s\n ”, a ) ; printf ( “ string b is : ” ) ; for ( i = 0 ; b[i] ! = ‘\0’ ; i + +) printf ( “ %c ”, b[i] ) ; printf ( “ \n ” ) ; } Iamaboy .\0ap1p1bp2p2二、二、 字符串指针作函数参数字符串指针作函数参数 用用字符数组名字符数组名和指向字符串的和指向字符串的指针指针变量变量作函数参数,均可以处理字符串。
作函数参数,均可以处理字符串 例例 9.20 用函数调用实现字符串的复制用函数调用实现字符串的复制I\0C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 (1) 用字符数组作函数参数用字符数组作函数参数 void copy_string ( char from[ ] , char to[ ] ) { int i = 0 ; while ( from [i] ! = ‘\0’ ) ( 先判断,后赋值先判断,后赋值 ) { to[i] = from [i] ; i + + ; } to[i] = ‘\0’ ; } main ( ) { char a[ ] = “ I am a teacher .” ; char b[ ] = “ you are a student .” ; printf ( “ string_a = %s\n string_b = %s\n ”, a , b ) ; copy_string ( a , b ) ;printf ( “ \n string_a = %s\n string_b = %s\n ”, a , b ) ; }C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 运行结果运行结果: string_a = I am a teacher . string_b = you are a student . string_a = I am a teacher . string_b = I am a teacher . 本程序本程序 main 函数中也可用字符型指针变量函数中也可用字符型指针变量。
改写如下改写如下: main ( ) { char *a = “ I am a teacher .” ; char *b = “ you are a student .” ; printf ( “ string_a = %s\n string_b = %s\n ”, a , b ) ; copy_string ( a , b ) ; printf ( “ \n string_a = %s\n string_b = %s\n ”, a , b ) ; }C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 (2) 形参用字符指针变量形参用字符指针变量 void copy_string ( char *from , char *to ) { for ( ; *from ! = ‘\0’ ; from + + , to + + ) *to = *from ; *to = ‘\0’ ; } main ( ) { char *a = “ I am a teacher .” ; char *b = “ you are a student .” ; printf ( “ string_a = %s\n string_b = %s\n ”, a , b ) ; copy_string ( a , b ) ;printf ( “ \n string_a = %s\n string_b = %s\n ”, a , b ) ; }C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 (3) 对对 copy_string 函数的简化函数的简化 a . void copy_string ( char *from , char *to ) { while ( (*to = *from ) ! = ‘\0’ ) { from + + ; to + + ; } } 即先赋值,后判断即先赋值,后判断。
故故 *to = ‘\0’ 语句语句不要不要 b. void copy_string ( char *from , char *to ) { while ( (*to + + = *from + + ) ! = ‘\0’ ) ; }注意分号C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 c. void copy_string ( char *from , char *to ) { while ( *from ! = ‘\0’ ) *to + + = *from + + ; *to = ‘\0’ ; } d. void copy_string ( char *from , char *to ) { while ( *from ) *to + + = *from + + ; *to = ‘\0’ ; } *from ! = ‘\0’ *from ! = 0while ( *from ! = 0 )C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 e. void copy_string ( char *from , char *to ) { while ( *to + + = *from + + ) ; } f. void copy_string ( char *from , char *to ) { for ( ; (*to + + = *from + + ) ! = ‘\0’ ; ) ; } for ( ; *to + + = *from + + ; ) ;C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 综上所述,用函数调用来处理字符串时,函数参数可以综上所述,用函数调用来处理字符串时,函数参数可以 有以下几种情况有以下几种情况: 实参实参 形参形参 1. 数数 组组 名名 数数 组组 名名 2. 数数 组组 名名 字符指针变量字符指针变量 3. 字符指针变量字符指针变量 字符指针变量字符指针变量 4. 字符指针变量字符指针变量 数数 组组 名名三三、、 字符指针变量与字符数组的区别字符指针变量与字符数组的区别 1. 字符数组由若干个元素构成,每一个元素中存放一字符数组由若干个元素构成,每一个元素中存放一 个字符。
而字符指针变量中存放的是字符串的首地个字符而字符指针变量中存放的是字符串的首地 址绝非将字符串放在字符指针变量中绝非将字符串放在字符指针变量中 2. 赋值方式可以不同如赋值方式可以不同如:C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 static char str[ ] = “ Hellow ” ; char *a = “ Hellow ” ; 对指针变量也可以对指针变量也可以: char *a ; a = “ Hellow ” ; 而而: static char str[10] ; str = “ Hellow ” ; 3. 数组定义后,在编译时就已分配内存单元,即有确定数组定义后,在编译时就已分配内存单元,即有确定 的值而对指针变量定义后,尽管系统给其分配了内的值而对指针变量定义后,尽管系统给其分配了内 存单元,但在没有明确指向前,其值是不确定的。
存单元,但在没有明确指向前,其值是不确定的 如如: char str[10] ; scanf ( “ %s ”, str ) ; 而而: char *a ; scanf ( “ %s ”, a ) ;不合法不合法( 可以可以 ) ( 不可以不可以 )合法合法C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 可改为可改为: char *a str[10] ; a = str; scanf ( “ %s ”, a ) ; 4. 指针变量的值可以改变,而数组名则不行指针变量的值可以改变,而数组名则不行 例例 9.21 (p240) main ( ) { char *a = “ I love China ! ” ; a = a + 7 ; printf ( “ %s ”, a ) ; } 运行结果运行结果: China ! 而下面程序则是错的而下面程序则是错的:C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 main ( ) { static char str[ ] = “ I love China ! ” ; str = str + 7 ; printf ( “ %s ”, str ) ; } 可改为可改为: main ( ) { static char str[ ] = “ I love China ! ” ; printf ( “ %s ”, str + 7 ) ; } 此时输出为此时输出为: China !C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 例例 9.22 (p240) main ( ) { char *a = “ I LOVE CHINA . ” ; int i ; printf ( “ The sixth character is %c \n ”, a[5] ) ; for ( i = 0 ; a[i] ! = ‘\0’ ; i + + ) printf ( “ %c ” , a[i] ) ; } 运行结果运行结果: The sixth character is E I LOVE CHINA . 指针变量带下标方式引指针变量带下标方式引用字符等价于用字符等价于 *( a + i )C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 5. 可用指针变量指向一个格式字符串,用以代替可用指针变量指向一个格式字符串,用以代替 printf 函数中的格式控制。
函数中的格式控制 如如: char *format ; format = “ a = %d , b = %f \n ” ; printf ( format , a , b ) ; 当然也可用字符数组当然也可用字符数组 如如: static char format[ ] = “ a = %d , b = %f \n ” ; printf ( format , a , b ) ; 由于不能对字符数组整体赋值,所以用指针变量就更由于不能对字符数组整体赋值,所以用指针变量就更 方便灵活方便灵活 如如: C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 char *format ; format = “ a = %d , b = %f \n ” ; printf ( format , a , b ) ; format = “ c = %c , d = %u \n ” ; printf ( format , c , d ) ; …… char format[ ] = “ a = %d , b = %f \n ” ; printf ( format , a , b ) ; format = “ c = %c , d = %u \n ” ; printf ( format , c , d ) ; …… C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 补例补例1: 下列程序输出结果为下列程序输出结果为 #include “ stdio.h” char fun ( char *s ) { if ( *s < = ‘Z’&& *s > = ‘A’ ) *s + = 32 ; return *s ; } main( ) { char c[80] = “ MyBook ” , *p ; p = c ; while ( *p) { *p = fun ( p ) ; putchar ( *p ) ; p + + ; } printf ( “ \n ” ) ; }mybookC语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 补例补例2: 下列程序输出结果为下列程序输出结果为 point1( int x , int y) { int t = 1 ; x = x + t ; y = y + t ; return ; } point2( int *x , int *y ) { int t = 1 ; *x = *x + t ; *y= *y + t ; return ; } void point3 ( char *p ) { p + = 1 ; *p = *p +1 ; }C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 main ( ) { char b[ 4 ]={ ‘a’, ‘c’, ‘s’, ‘f’ } , *pt = b ; int x = 3 , y = 4 ; point1( x , y ) ; 31 printf ( “ %d , %d \n ”, x , y ) ; point2( &x , &y ) ; 32 printf ( “ %d , %d \n ”, x , y ) ; point3( pt ) ; 33 printf ( “ %c \n ”, *( pt + 1) ) ; } 31 32 333 , 44 , 5dC语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院§9.5 函数的指针和指向函数的指针变量一、用函数指针变量调用函数 函数的指针: 函数的入口地址 函数的指针变量: 指向函数入口地址的指针变量 一个已定义的函数在编译时,系统为其分配一个入口 地址,并用函数名表示。
通过指向函数的指针变量,也 可以调用函数 指向函数的指针变量的一般定义形式: 数据类型 (*标识符) ( ) ; 其中: 数据类型是指函数返回值的类型 如: int (*p ) ( ) ; 例 9.23 (p241) 求 a 和 b 中的大者C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 main ( ) { int max( int , int ) ; int max( ) ; int a , b , c ; scanf ( “ %d ,%d ” , &a , &b) ; c = max ( a , b ) ; printf ( “ a = %d , b = %d , max = %d ” , a , b , c ) ; } max ( int x , int y ) { int z ; if ( x > y ) z = x ; else z = y ; return ( z ) ; }C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 本例也可在本例也可在 main 函数中,用指向函数的指针变量来调函数中,用指向函数的指针变量来调 用用 max 函数。
函数 如如: main ( ) { int max( ) ; int (*p ) ( ) ; int a , b , c ; p = max ; scanf ( “ %d ,%d ” , &a , &b) ; c = (*p ) (a , b ) ; c = max( a , b ) ; printf ( “ a = %d , b = %d , max = %d ” , a , b , c ) ; } 说明说明: 1. C语言中,函数调用可以有两种形式语言中,函数调用可以有两种形式 即即 函数名函数名调用和调用和函数指针函数指针调用定义指向函数的指针变量定义指向函数的指针变量C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 2. (*p ) ( ) 表示表示一个指向函数的指针变量,用于存放函一个指向函数的指针变量,用于存放函 数的入口地址。
数的入口地址 若把某一个函数的入口地址赋给它,若把某一个函数的入口地址赋给它,它就指向该函数即在程序中一个函数指针变量可以它就指向该函数即在程序中一个函数指针变量可以 先后指向不同的函数先后指向不同的函数 3. 对于指向函数的指针变量作自增或自减运算均无意对于指向函数的指针变量作自增或自减运算均无意义如义如: int (*p ) ( ) ; 则则: p + + ; p + n ; – – p ; ( 均无意义均无意义 ) 因为因为 p 只能指向函数的入口地址,而不能指向函数只能指向函数的入口地址,而不能指向函数内的某一条指令内的某一条指令 二、用指向函数的指针变量作函数参数二、用指向函数的指针变量作函数参数 函数指针变量作函数参数函数指针变量作函数参数 时,它是将时,它是将函数名函数名(即函数即函数 的的入口地址入口地址) 传给形参传给形参 C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 如如: main( ) { ……. sub ( f1 , f2 ) ; ……. sub ( f3 , f4 ) ; } sub ( int (*x1 ) ( int ) , int (*x2 ) ( int , int ) ) { int a , b , i , j ; a = (*x1 ) ( i ) ; a = f1( i ) b = (*x2 ) ( i , j ) ; b = f2( i , j ) …… } f1函数函数x1f1f2函数函数x2f2f3函数函数x1f3f4函数函数x2f4优点优点: 程序中要多次调用程序中要多次调用 sub 函数,且每次要调用的函数函数,且每次要调用的函数不固定时,只需给出不同的不固定时,只需给出不同的函数名作实参函数名作实参即可。
而即可而 sub 函函数不必作任何修改,这符合结构化程序设计方法的原则数不必作任何修改,这符合结构化程序设计方法的原则C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 例例 9.24 main ( ) { int max ( int , int ) , min ( int , int ) , add (int , int ) ; int a , b ; printf ( “ enter a and b :” ) ; scanf ( “ %d , %d ”, &a , &b ) ; printf ( “ max = ” ) ; process ( a , b , max ) ; printf ( “ min = ” ) ; process ( a , b , min ) ; printf ( “ sum = ” ) ; process ( a , b , add ) ; }C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 max ( int x , int y ) { int z ; if (x > y ) z = x ; else z = y ; return ( z ) ; } min ( int x , int y ) { int z ; if (x < y ) z = x ; else z = y ; return ( z ) ; }C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 add ( int x , itn y ) { int z ; z = x + y ; return ( z ) ; } process ( itn x , int y , int (*fun ) ( int , int ) ) { int result ; result = (*fun ) ( x , y ) ; printf ( “ %d\n”, result ) ; }max函数函数add函数函数min函数函数funfunfunC语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 运行结果运行结果: enter a and b : 2 , 6 max = 6 min = 2 sum = 8 说明说明: main 函数的第二行不能少。
因为在用函数指针变量函数的第二行不能少因为在用函数指针变量调用函数是用函数名作实参为保证编译系统正确判调用函数是用函数名作实参为保证编译系统正确判 别它是别它是函数名函数名,必须作说明必须作说明 C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院§9.6 返回指针值的函数返回指针值的函数 一一、、 定义定义 格式格式: 数据类型数据类型 *函数名函数名 ( 参数表参数表 ) { 函数体函数体 } 如如: int *fun ( int *x , int y ) { ……. return x ; } 调用此函数能得到一个指向整型数据的指针调用此函数能得到一个指向整型数据的指针( 地址地址)C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 #include “stdio.h” int *fun (int *x , int n , int y ) { int i = 0 ; for ( ; i < n ; i + + , x + + ) if ( *x = = y ) return x ; return NULL ; } main( ) { int a[6 ] = { 4 , 5, 2 , 6 ,10 , 8 } , *p , t ; scanf ( “ %d ” , & t ) ; p = fun( a , 6 , t ) ; printf ( “ %d \n ” , *p ) ; } 运行时若输入运行时若输入 8 则输出为则输出为 8 C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院§9.7 指针数组和指向指针的指针指针数组和指向指针的指针一、指针数组的概念一、指针数组的概念 由同一数据类型的指针变量构成的数组叫由同一数据类型的指针变量构成的数组叫指针数组指针数组。
即一个数组的所有元素均为指针型数据即一个数组的所有元素均为指针型数据 定义格式定义格式: 类型标识符类型标识符 *数组名数组名[数组长度数组长度] 如如: int *p[4] ; 即表示指针数组即表示指针数组 p 有四个元素每一个元素都是指针有四个元素每一个元素都是指针 变量,且可以指向一个整型变量指针数组的下标仍变量,且可以指向一个整型变量指针数组的下标仍 从从 0 开始计 例例9.27 将若干个字符串按字母顺序将若干个字符串按字母顺序(由由小小到到大大)输出 (也叫按也叫按字典顺序输出字典顺序输出 )C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 #include “string.h” main ( ) { void sort ( ) ; void print ( ) ; static char *name[ ] = {“Follow me ”, “ BASIC ” , “Greatwall ”, “FORTRAN ”, “ Computer design ” } ; int n = 5 ; sort ( name , n ) ; print ( name , n ) ; } void sort (char *name[ ] , int n )name[0]name[1]name[2]name[3]name[4]Follow meBASICGreat wallFORTRANComputer designname 数组name[0]name[1]name[2]name[3]name[4]Follow meBASICGreat wallname 数组FORTRANComputer designC语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 { char *temp ; int i , j , k ; for ( i = 0 ; i < n – 1 ; i + + ) { k = i ; for ( j = i + 1 ; j < n ; j + + ) if ( strcmp ( name[k] , name[j] ) > 0 ) k = j ; if ( k ! = i ) {temp = name[i] ; name[i] = name[k]; name[k] = temp ; } } } void print ( char *name[ ] , int n ) { int i ; for ( i = 0 ; i < n ; i + + ) printf ( “ %s \n ”, name[i] ) ; }指针变量指针变量,表示字符串的首地址表示字符串的首地址C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 运行结果运行结果: BASIC Computer design FORTRAN Follow me Great Wall 本例是通过改变指针数组中各元素的值,即字符串的首本例是通过改变指针数组中各元素的值,即字符串的首 地址方式,在不改变字符串位置的情况下,达到排序的地址方式,在不改变字符串位置的情况下,达到排序的 目的的。
目的的 sort 函数可改为函数可改为:C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 (1) void sort ( char *name[ ] , int n ) { char *temp ; int i , j ; for ( i = 0 ; i < n 1 ; i + + ) for( j = i + 1 ; j < n ; j + + ) if ( strcmp (name[i] , name[j] ) > 0 ) { temp=name[i] ; name[i] = name[j] ; name[j] = temp ; } } (2) void sort (char *name[ ] , int n ) { char temp[81] ; int i , j ; C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 for ( i = 0 ; i < n 1 ; i + + ) for( j = 0 ; j < n i 1 ; j + + ) if ( strcmp ( nname[ j ] , name[ j +1 ] ) > 0 ) { strcpy( temp , name[j] ) ; strcpy(name[j] , name[j +1] ) ; strcpy(name[j+1] , temp ) ; } } 另外另外 print 函数也可改为函数也可改为: void print ( char *name[ ] , int n ) { int i = 0 ; char *p ; p = name[0] ; while ( i < n )C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 { p = *( name + i + + ) ; printf ( “ %s \n ” , p ) ; }二、二、 指向指针的指针指向指针的指针 表示一个指向字符指针变量的指针变量。
表示一个指向字符指针变量的指针变量即即: p 中只能存放一个指向字符型数据的指针变量的地址中只能存放一个指向字符型数据的指针变量的地址先求先求*( name + i ) 的值的值, 即即name[i] 再使再使 i 自增自增pq&ap6a 定义格式定义格式: 数据类型数据类型 **标识符标识符 如:如: char **p ; C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 main ( ) { static char *name[ ] = {“Follow me ”, “ BASIC ” , “Greatwall ”, “FORTRAN ”, “ Computer design ” } ; char **p ; int i ; for ( i = 0 ; i < 5 ; i + + ) { p = name + i ; 表示表示 name[i] 的地址的地址 printf ( “ %s \n” , *p ) ; } 运行结果运行结果: Follow me BASIC Great Wall FORTRAN Computer designname[0]name[1]name[2]name[3]name[4]Follow meBASICGreat wallFORTRANComputer designname 数组数组p pC语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 说明说明: 指针数组的元素也可以指向整型数据或实型数据。
如指针数组的元素也可以指向整型数据或实型数据如: 例例 9.29 main ( ) { int a[5] = { 1 , 3 , 5 , 7 , 9 } ; static int *num[5] ={&a[0], &a[1], &a[2], &a[3], &a[4]} ; int **p , i ; p = num ; for ( i = 0 ; i < 5 ; i + + ) { printf ( “%d\t”, **p ) ; p + + ; } } 运行结果运行结果: 1 3 5 7 9 num[0] num[1] num[2] num[3] num[4]a[0] = 1a[1] = 3a[2] = 5 a[3] = 7 a[4] = 9 p num aC语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 注意注意: 程序中程序中*p 是是 p 间接指向的对象的间接指向的对象的地址地址。
而而 **p 是是 p 间接指向的对象的间接指向的对象的值值三、三、 指针数组作指针数组作 main 函数的形参函数的形参 命令行的一般形式命令行的一般形式: 命令名命令名 参数参数 1 参数参数 2 …… 参数参数 n 如如: file1 China Beijing copy d:\f1.c e:\file .c 带参数的带参数的 main 函数的一般形式函数的一般形式: main ( int argc , char *argv[ ] ) { …… } char **argvC语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 其中其中: argc 是命令行中参数的个数是命令行中参数的个数 (包括命令名包括命令名) argv 是一个指向字符串的指针数组。
是一个指向字符串的指针数组 例如例如: main ( int argc , char *argv[ ] ) { while ( argc > 1 ) { + + argv ; printf ( “ % s \n”, *argv ) ; – – argc ; } } file 1 \0C h in a \0B e ijing \0argv[0]argv[1]argv[2]argvC语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 若输入的命令行为若输入的命令行为: file1 China Beijing 则输出为则输出为: China Beijing 上述程序也可改为上述程序也可改为: main ( int argc , char *argv[ ] ) { while ( argc – – > 1 ) printf ( “ % s \n”, * + + argv ) ; } 先进行先进行+ + argv 计算计算C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 又如具有又如具有“ 参数回送参数回送 ” 功能的功能的 C 程序程序 (假定源文件名为假定源文件名为 echo.c) main ( int argc , char *argv[ ] ) { while ( – – argc > 0 ) printf ( “ % s %c\n”, * + + argv , (argc > 1) ? ‘ ’ : ‘\n’) ; } 如输入命令行如输入命令行: echo Computer and C Language 则在显示屏上输出则在显示屏上输出: Computer and C Language 此程序也可改为此程序也可改为:C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 main ( int argc , char *argv[ ] ) { int i ; for ( i = 1 ; i < argc ; i + + ) printf ( “ % s %c ”, argv[i] , ( i < argc – 1) ? ‘ ’ : ‘\n’ ) ; } C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院作业:作业:P P258 10.1 10.3 10.8 10.16 10.1710.1 10.3 10.8 10.16 10.17C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院§9.8 有关指针的数据类型和指针运算的小结( 自学 )C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院9.9 动态内存分配动态内存分配一、动态内存分配函数一、动态内存分配函数 1. 动态数据结构动态数据结构 前述各种数组,其元素在内存中存储时占用连续的内前述各种数组,其元素在内存中存储时占用连续的内存空间。
存空间 所占据内存空间的位置和大小是在数组被定义所占据内存空间的位置和大小是在数组被定义说明的同时由系统分配的,且在程序运行期间不改变说明的同时由系统分配的,且在程序运行期间不改变 这种数据结构叫这种数据结构叫 “ 静态数据结构静态数据结构 ” 若数据所占用的若数据所占用的内内 存空间的位置和大小随程序的运行而动态变化,则这种存空间的位置和大小随程序的运行而动态变化,则这种 数据结构叫数据结构叫 “ 动态数据结构动态数据结构 ”其特点是其特点是: 各数据在各数据在逻逻辑辑 上上是连续排列的但在是连续排列的但在物理上物理上并不真正连续即在内存并不真正连续即在内存 中存储时并不占用连续的内存空间中存储时并不占用连续的内存空间C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 2. 动态内存分配函数动态内存分配函数 (1) malloc 函数函数 作用作用: 为数据为数据动态分配动态分配内存单元内存单元 格式格式: void * malloc ( size ) 说明说明 : a. 参数参数 size 表示要求分配的内存空间表示要求分配的内存空间字节数字节数。
即调用本函数时,它在内存中分配大小为即调用本函数时,它在内存中分配大小为 size 字节字节 的空间 b. 调用本函数,正常时该函数返回所分配内存单元调用本函数,正常时该函数返回所分配内存单元 的的起始地址起始地址如内存中已没有足够的空间,则返如内存中已没有足够的空间,则返 回零回零(NULL),, 即返回即返回空指针空指针 c. 由于由于 malloc 函数的返回值是函数的返回值是 void 型的指针因型的指针因 此在把返回值赋给具有一定数据类型的指针变量此在把返回值赋给具有一定数据类型的指针变量 时,应该对返回值实行强制类型转换时,应该对返回值实行强制类型转换 C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 d. 调用调用 malloc 函数,应在源程序开头用函数,应在源程序开头用 : #include “ malloc . h ” ( Turbo C 中为中为: alloc . h ) 例例: 在内存中为在内存中为 80 个字符动态分配内存个字符动态分配内存 # include “alloc . h ” main ( ) { char *p ; p = ( char * ) malloc ( 80 * sizeof ( char ) ) ; if ( p = = 0 ) { printf ( “ out of memory \n ” ) ; exit (0) ; } } 其中其中: malloc ( ) 的返值用的返值用 ( char *) 强制转换为字符型强制转换为字符型指指 针。
针 用用sizeof 函数测试数据类型的大小函数测试数据类型的大小C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院 (2) free ( ) 函数函数 作用作用: 用于用于释放释放 malloc 函数分配的内存空间函数分配的内存空间. 格式格式: void free ( p ) 说明说明: 1. p 为指针变量为指针变量 调用该函数,则把调用该函数,则把 p 所指向的内所指向的内 存空间释放,被释放的空间可以重新分配存空间释放,被释放的空间可以重新分配 2. p 所指向的必须是在此之前使用所指向的必须是在此之前使用 malloc 函数分配函数分配 的内存空间而被释放的空间大小,则由使用的内存空间而被释放的空间大小,则由使用 malloc 函数时参数函数时参数 size 决定 3. 只有调用只有调用 malloc 函数时分配的内存空间才能用函数时分配的内存空间才能用 free 函数释放。
否则,可能会导致错误函数释放否则,可能会导致错误C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院例例: 为为 40 个个 int 数据动态分配空间并赋值和输出数据动态分配空间并赋值和输出 # include “ stdio.h” # include “alloc.h” main ( ) { int i , *p ; p = ( int * ) malloc ( 40 * sizeof ( int ) ) ; if ( p = = NULL ) { printf ( “ out of memory \n ” ) ; exit (0) ; } for ( i = 0 ; i < 40 ; i + + ) *( p + i ) = i ; for ( i = 0 ; i < 40 ; i + + ) printf ( “ %d ” , *( p + i ) ) ; free ( p ) ; } C语语言言程程序序设设计计第第九九章章四川理工学院四川理工学院四川理工学院四川理工学院。












