1、第 九 章 指 针,9.1 指针的概念,9.2 变量的指针和指向变量的指针变量,9.3 数组的指针和指向数组的指针变量,9.4 字符串的指针和指向字符串的指针变量,9.5 函数的指针和指向函数的指针变量,9.6 返回指针值的函数,9.7 指针数组和指向指针的指针,9.8 指针小结,9.9 动态内存分配,第九章 指 针,本章要点: 了解地址与指针的概念 熟练掌握指针变量的定义、初始化及指针的运算 掌握指针与数组、指针数组、二级指针等知识 熟练掌握字符串的指针与指向字符串的指针变量 了解指针与函数的概念 掌握指针作为函数参数的应用 了解多维数组指针的概念,指针是C语言中最重要的组成部分。利用指针可
2、以表示:复杂的数据结构;动态分配内存;灵活处理字符串和数组;直接处理内存地址;从函数调用中获取多个值等。,对变量值的存取实质上是通过地址进行的。,示意图,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
3、,例,图,如: int i = 3 ;printf ( “ %d ” , i ) ; 执行是:根据变量名 i 找到 i 的地址 ( 如: 2000 ),然后 从地址 2000 开始的两个字节中取出数据(即变量的值 3),再将其输出。这种据变量名按变量地址存取变量的值的 方式叫 “ 直接访问 ”方式。,说明,重点,指针: 一个变量的地址叫该变量的 “ 指针 ”。指针变量: 用于存放其它变量的地址的变量。 指向:如 i_pointer= &i ,就称i_pointer指向变量 i目标变量: 指针变量所指向的变量。,有关指针的几个概念:,说明: 1. 类型说明符表示指针变量所指向的变量的类型,同类型
4、变量的地址才能放到指向该类型变量的指针变量中。例如 2. 不能把一个整型量或其它非地址类型的数据赋给一个指针变量。例如,示例一 实例二,9.2 变量的指针和指向变量的指针变量一、指针变量的定义,格式: 类型说明符 * 标识符,如: int *pointer_1, *pointer_2 ; float *fp1 , *fp2 ;,例,例,float f1 ; int *p ; p = (不正确),例,如: int *p ; p = 100 ; (不合法) 但: p=NULL 或 p=0 或 p=0 合法, 表示为指针变量赋“空值”,含义是: p 不指向任何单元。,例,二、指针变量的引用 例 9.
5、1 通过指针变量访问整型变量main ( ) int a , b ;int *p1 , *p2 ; a = 100 ; b = 10 ;p1 = ,“直接访问”方式,“间接访问”方式, *p1 表示指针变量 p1所指向的变量,即 a,运行结果,分析,结果: 100, 10100, 10,关于 & 与 * 运算符的说明:1. & 是取地址运算符, 如: &a, &b等。定义时,* 是指针运算符,用于表示其后的标 识符是指针变量。但在程序中,*p 则表示指针变量 p 所指向的变量,即目标变量。2. & , * , + + , 同优先级, 按从右至左方向结合。,示例1 示例2 示例3,如: int
6、a , *p1 , *p2 ;p1 = 则: p2 也指向变量 a,例1,例2,如: int a , *p1 ; p1 = 则: (*p1)+ 等价于 a+ 注意: *p1+ 不等价于 (*p1)+ 因为: *p1+ 等价于 *( p1+ ) 即:先得 p1 所指向变量的值,再使指针变量 p1的值自增。,例3,程序运行,注意事项,数据指针交换示意图,例 9.2 输入两个数,按从大到小的顺序输出。main ( ) int *p1 , *p2 , *p , a , b ;scanf(“ %d , %d ” , ,进行地址交换,本程序是采用交换变量 a 和 b 的地址来实现两个数的比较的,且比较前后
7、 a , b 的值并未发生变化。,图,如输入: 5 , 9 则输出: a = 5 , b = 9max = 9 , min = 5,三、 指针变量作为函数的参数函数调用时,把实参的值传递给形参。指针变量可以作实际参数,其作用也是将实际参数的值传递给形式参数,但此时的值代表是一个变量的地址,把地址传送给被调函数的形式参数。,例 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”,
8、 ,单步运行,运行结果,注意,通过指针运算,间接交换主调函数中的 a 和 b 的值,而 p1和 p2 的值不变。,若输入: 5 , 9 输出为: 9 , 5,如果把 swap 函数改成 :swap (int *p1 , int *p2 ) int *p ;*p = *p1 ; *p1 = *p2 ; *p2 = *p ;,此句有问题!,典型错误一,swap(int x , int y ) int t ;t=x; x=y; y=t ; ,5,5,9,9,5,9,9,5,a,b,x,y,a,b,x,y,(a),(b),main ( ) int a , b ;scanf (“ %d , %d ” ,
9、 ,典型错误二,实例,实例,说明: 1. 如想通过函数调用得到 n 个要改变的值。 在主调函数中设 n 个变量,并用 n 个指针变量指向它们。 将指针变量作实参,使 n 个变量的地址传给所调用的函数形参。 通过形参指针变量,改变该 n 个变量的值。 主调函数中就可以使用这些改变了值的变量。 2. 形参指针变量自身值的变化不会使实参指针变量的值发生改变。 3. 可以通过改变形参指针变量所指向的变量的值来改变实参指针变量所指向的变量的值。,swap (int *p1 , int *p2 ) int *p ;p = p1 ; p1 = p2 ;p2 = p ;main ( ) int a , b ,
10、 *pointer_1 , *pointer_2 ;scanf ( “ %d , %d ” , ,本函数中试图通过改变形参指针变 量的值来使实参指针变量的值改变,典型错误三,错 误 原 因,例 9.4 swap ( int *pt1, int *pt2 ); exchange ( int *q1 , int *q2 , int *q3 ); main ( ) int a , b , c , *p1 , *p2 , *p3 ;scanf ( “ %d , %d , %d ”, ,swap ( int *pt1, int *pt2 ) int p ;p = *pt1 ; *pt1 = *pt2 ;
11、 *pt2 = p ;,9,0,10,p1,a,b,c,p2,p3,9,0,10,q1,b,c,q2,q3,a,exchange,9,0,pt1,b,pt2,a,swap,p1,q1,p1,运行如下: 9, 0,10 10,9,0,运行,数组的指针: 数组的起始地址( 首地址 )数组元素的指针: 数组元素的地址,9.3 数组的指针和指向数组的指针变量C 语言中,指针变量可以指向变量,也可 以指向数组和数组元素。,一、指向一维数组的指针变量的定义与赋值指向数组的指针变量的定义同指向变量的指针变量的定义相同。 例如: int a10 ; int *p ;如果: p= 的含义是将数组的首地址赋给指针
12、变量 p ,而不是赋给 ( *p ) 。,二、通过指针引用数组元素如: int a10, *p;p = a ;,&a0,1,3,20,a0,a1,a9,p,&a1,p+1,说明:1. 数组元素在内存中是连续存放的。2. (p+i) 表示指向 ai 的地址,a+i 也表示 ai 的地址,故 (p+i) 等价于 a+i。 3. 指向数组的指针变量可以带下标。如: pi。,a,C 语言规定,指针变量 p+1 指向下一个元素。若数组元素为实型,则 p+1 表示的实际地址为:p+1d=p+1 4 ( d 为一个数组元素所占的字节数),a+1,&ai,p+i,a+i,&a9,p+9,a+9,ai,*(p+
13、i),*(p+1),*p,*(p+9),*(a+i),*(a+1),*a,*(a+9),p0,p1,p9,pi,补充,数组元素的引用 例9.5 用三种方法输出数组各元素。 (1) 下标法: 数组名下标 或 指针变量名下标 例一 例二 (2) 用数组名计算元素地址 设:int a10, *p=a; 则:*(p+i) 或 *(a+i)表示元素 举例 (3) 用指针变量指向数组元素 举例,下标法(指针变量名下标) main ( ) int a10 , *p, i ;for ( i = 0 ; i 10 ; i+ )scanf ( “ %d ”, ,用数组名计算元素地址 main ( ) int a1
14、0 , i ;for ( i = 0; i 10; i+ ) scanf (“%d”, ,用指针变量指向数组元素main ( ) int a10 , i , *p ;for ( i = 0 ; i 10 ; i+ )scanf ( “ %d ”, ,下标法(数组名下标) main ( ) int a10 , i ;for ( i = 0 ; i 10 ; i+ )scanf ( “ %d ”, ,注意:(1) 指针变量可以作自增,自减运算。如: +p, p 但数组名是常量不能作自增、自减运算。如: a+, a 等均不合法。 (2) 注意指针变量的当前值。 错例 正例 (3) 注意指针变量的运算
15、如: int a10 , i , *p ; p = a ; 则: p+ (或 p += 1 )表示 p 指向 a1 , 此时若执行*p 则取出 a1 元素的值。 “*” 与 “+” 同优先级,自右往左结合。例如 (*p)+ 表示目标变量值加 1,指针变量值不变。 *(p+) 等价于 ai+ *(+p) 等价于 a+i 即:p先自增,再作*运算。,while 循环实现的实例1 实例2,main ( ) int a10 , i , *p; p = a ; for ( i = 0 ; i 10 ; i+ )scanf ( “ %d ”, p+ ) ;printf ( “ n” ) ;for ( i
16、= 0 ; i 10 ; i+ , p+ )printf ( “%d ”, *p ) ;,错例,main ( ) int a10 , i , *p; p = a ; for ( i = 0 ; i 10 ; i+ )scanf ( “ %d ”, p+ ) ;printf ( “ n” ) ;for (i = 0, p=a; i 10 ; i+, p+)/* 或 for(p=a; pa+0;p+) */printf ( “%d ”, *p ) ;,正例,main ( ) int a100 , *p ;p = a ; while ( p a +100 )printf(“%d”, *p+) ; ,
17、1,main ( ) int a100 , *p ;p = a ; while ( p a +100 ) printf(“%d”,*p) ;p+ ; ,2,*p+ 等效于 *(p+) , 即先取 p 所指向变量的值,再使 p + 1。 即:*p+先取 *p的值,后使p+1;*(p+) 与*(+p) 的作用不同。 *(+p) 先使 p+1,再取 *p 的值 。,实例,main ( ) int array10 ; f ( array, 10 ) ; ,三、数组名作函数参数对数组名作函数参数时,实际上是将实参数组的首地址传给形参,实参数组与形参数组共占同一段内存。在调用函数过程中,形参数组中元素值发
18、生变化也就使实参数组的元素值随之而发生变化。,f (int arr , int n) ,动画演示,例 9.7 将数组 a 中 n 个整数按相反顺序存放。 算法:将第一个元素和最后一个元素对换,将第二个同倒数第二个对换. .即两两对换,直到:a(n1)/2 与 an(n1)/21 对换为止。,3,7,9,11,0,6,7,5,4,2,2,4,5,7,6,0,11,9,7,3,i,m,j,void inv (int x , int n) int t, i, j, m =(n1)/2 ;for (i = 0; i = m; i+) j = n 1 i ;t = xi ; xi = xj ; xj =
19、 t ; return; /* 可去掉 */,数组颠倒函数,main ( ) static int i,a10=3, 7,9, 11, 0, 6, 7, 5, 4, 2 ;printf ( “ The original array: n ” ) ;for ( i = 0 ; i 10 ; i + + )printf ( “ %d , ”, ai ) ;printf ( “ n ” ) ;inv ( a , 10 ) ;printf(“The array has been inverted: n ”);for ( i = 0 ; i 10; i+ )printf(“%d , ”, ai ) ;
20、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,运行结果,以上程序也可以改为如下: void inv ( int *x , int n ) int *p, t, *i, *j, m;m = (n 1)/2 ;i = x ; j = x + n 1 ; p = x + m ;for ( ; i = p ; i+, j ) t = *i ; *i
21、= *j ; *j = t ; return ; ,a 数组,a0,a1,a9,3,7,0,i , x,p = x+m,j,2,4,5,7,6,11,9,(1) 二者都用数组名main ( ) f ( int x , int n ) int a10 ; f ( a , 10 ) ; 特点: a 和 x 数组共用同一段内存单元。,综上所述:对于实参数组想在被调函数中改变此数组元素的值,实参与形参的对应关系可以如下:,(2) 实参为数组名,形参用指针变量main ( ) f ( int *x , int n ) int a10 ; f ( a , 10 ) ; 特点: 实参将数组的首地址传给形参指
22、针变量,通过 指针变量指向实参数组,进而对其作相应的处理。,(3) 二者都用指针变量main ( ) f ( int *x , int n ) int a10 , *p ; p = a ; f ( p , 10 ) ; 特点:先使 p 指向 a 数组,再将 p 传给 x ,使 x 也指向 a 数组,从而进行处理。,(4) 实参为指针变量,而形参为数组名 main ( ) f ( int x , int n ) int a10 , *p ; p = a ; f ( p , 10 ) ; 特点: 利用指针变量将 a 数组的首地址传给 x 数组。使两数组共用同一段内存单元。利用xi值的变化, 使ai
23、的值也发生变化。 注意: 上述四种处理方式中,当用指针变量作实参时, 必须先使指针变量有确定的值,即指向一个已定义的数组。,四、二维数组的指针和指向二维数组的指针变量1. 二维数组和数组元素的地址C 语言中二维数组实际上是由若干个按行存放的 一维数组构成的。如: int a34 ;a0 a00 a01 a02 a03 a1 a10 a11 a12 a13 a2 a20 a21 a22 a23 a 代表首元素的地址,此时首元素a0又是一个包 含有4个元素的一维数组。所以 a (或 a + 0 )表示二维数 组第0 行的地址。a+1,a+2 分别表示二维数组第 1 行 和第 2 行的地址。所以二维
24、数组名是一个行指针。,a,a0, a1, a2分别表示一维数组名,所以a0代表一维数组a0中第 0 列元素的地址即 &a00。同理: a1等价于&a10, a2等价于&a20。 二维数组元素的地址可表示为:(1) &aij (2) ai + j(3) * (a + i ) + j ( 因为 ai 等价于 * (a + i ) ) 二维数组元素的引用可表示为:(1) aij (2) * ( ai + j )(3) * (* (a + i ) + j ),1 3 5 7,2 4 6 8,1112 13 14,p,p +1,2. 指向二维数组的指针变量(1) 指向二维数组的列指针变量int a34
25、, *p ;p=a0; ( 或: p = 原因: a0 是一个列地址,a 是一个行地址。,#include “stdio.h” void main ( ) int a34=1, 2, 3, 4, 9, 8, 7, 6, 10, 11, 5, 2 ;int *p = a0; for ( ; p a0 +12 ; p+ ) if ( p a0 ) %4 = = 0 ) printf( “n”) ;printf( “%4d” , *p ) ;,列指针变量举例,int *p = ,所以,定义格式: 数据类型 (* 标识符 )常量如: int ( *p)4 ; 表示: p 所指的对象是有 4 个整型元素
26、的数组。int a34 , ( *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 = a0 。,(2) 指向二维数组的行指针变量由于二维数组是由按行存放的一维数组构成,C语言中可以用行指针变量来引用二维数组元素。,行指针变量举例:输出二维数组任意行任意列元素的值。void main ( ) int a34= 1, 2,
27、3, 4, 9, 8, 7, 6, 10, 11, 5, 2 ;int ( *p)4 , i , j ; p = a ; scnaf( “ %d ,%d ” , ,*(*( a+i )+j ) ;,3. 补充实例用函数调用方式编写程序找出二维数组 a 中每 行的最小值并输出。 要求: 二维数组元素的值用随机函数产生( 0 50)之间; 每行中元素的最小值在 line_min( ) 函数中求出; 在主函数中输出每行的最小值。,void main( ) 1、 定义一个二维数组2、 调随机函数对二维数组元素赋值3、 调用 line_min 函数4、 输出结果到屏幕,line_min ( ) 1、 接
28、收实参2、求二维数组每行中的最小值 ,方法一、用列指针来求解#include “stdlib.h” #define N 3#define M 4void main ( ) int aNM , min , i , j ; for( i = 0 ; i N ; i+)for( j = 0 ; j M ; j+) aij= random( 50 ) ;printf(“%4d”, aij ) ;if( j+1)%4 = = 0 ) printf(“n” ) ; for( i = 0 ; i N ; i+) min = line_min( ai ) ; printf(“a%d: min = %d n”,
29、 i, min ) ; ,line_min函数,line_min ( int * p ) int j , min ;min= *(p + 0) ;for( j = 1 ; j *( p + j ) ) min = * ( p + j ) ; return min ; ,#include “stdlib.h” #define N 3#define M 4void main ( ) int aNM , min , i , j ; for (i = 0; i N; i+)for (j = 0; j M; j+) aij= random(50);printf(“%4d”, aij);if( j+1)%
30、4 = = 0 ) printf(“n”); for( i = 0 ; i N ; i+) min = line_min( a + i ) ; printf(“a%d: min=%d n”, i, min); ,方法二、用行指针求解,line_min ( int (* p)M ) int j , min ;min= * (*p) ;for( j = 1 ; j * (*p + j ) min = * (*p + j) ; return min ; ,line_min函数,说明:random(x) 函数产生一个 ( 0 x1) 间 的随机整数, 相关的函数有: rand( )函数产生 0 327
31、67间的随机数。 如: rand( )%100 可产生0 99 的整数。 (rand( )%90 + 10.0 ) / 10.0可产生 1.0 10.0 之间的实数。,说明,41,9.4 字符串的指针和指向字符串的指针变量字符串的指针就是字符串的首地址。一、 字符串的表示形式1、 用字符数组实现例 9.16 main ( ) char string = “I Love China”;printf (“%sn”, string ) ; ,其中 string 是数组名,表示字符数组的首地址。stringi 表示数组中的一个元素。如: string4 代表 第 5 个元素,即 字母 v 。,42,2
32、、用字符指针实现 例 9.17 main ( ) char *string = “I Love China”;printf ( “ %sn ” , string ) ; ,注意: C 语言中对字符串可以进行整体输入和输出。 而对数值型数组则不能用数组名来输出它的全 部元素,只能逐个元素输出。,含义及说明,char *string ; string = “ I Love China ” ;,含义及说明 将字符串的首地址赋给指针变量 string 。 说明:尽管没有直接定义字符型数组,但实际上 C 语言对字符串常量均按字符数组来处理。即在内存中开辟了一个字符数组用来存放字符串常量。,注意,43,例
33、 9.18 将字符串 a 复制到字符串 b 。 main ( ) char a = “I am a boy .”, b20 ;for ( i = 0; *(a+i)!=0; i+)*(b+i)=*(a+i);*( b + i ) = 0 ;printf(“string a is: %s n ”, a ) ;printf(“string b is : ” ) ;for ( i = 0 ; bi ! = 0 ; i+)printf ( “ %c ”, bi ) ;printf ( “ n ” ) ;,3. 对字符串的处理可以用下标法,也可用指针法。,运行结果:string a is: I am a
34、 boy .string b is: I am a boy .,运行结果,44,例 9.19 用指针变量来处理。 main ( ) char a =“I am a boy”, b20;char *p1, *p2;int i ; p1 = a ; p2 = b ;for ( ;*p1 != 0; p1+,p2+) *p2 = *p1 ; *p2 = 0 ; printf(“string a is: %sn ”, a ); printf ( “ string b is : ” ) ; for ( i = 0 ; bi ! = 0 ; i+)printf ( “ %c ”, bi ) ; print
35、f ( “ n ” ) ; ,I,a,m,a,b,o,y,.,0,a,p1,p1,b,p2,p2,I,0,45,(1) 用字符数组作函数参数实现字符串复制。void copy_string (char from , char to ) int i = 0 ;while ( from i != 0 ) toi = from i ; i + + ; toi = 0 ; ,main ( ) char a = “ I am a teacher .” ;char b = “ you are a student .” ;printf(“string_a=%sn string_b=%sn”,a,b) ;co
36、py_string ( a , b ) ;printf ( “ n str_a = %sn str_b = %sn ”, a,b ) ;,二、字符串指针作函数参数,运行结果,运行结果:string_a = I am a teacher .string_b = you are a student .string_a = I am a teacher .string_b = I am a teacher .,46,main ( ) char *a = “ I am a teacher .” ;char *b = “ you are a student .”;printf(“str_a=%sn st
37、r_b=%sn”, a, b);copy_string ( a , b ) ; printf(“n str_a=%sn str_b=%sn ”, a, b); ,(2) 主调函数: main 函数中改用字符型指针变量void copy_string(char from , char to ) int i = 0 ;while ( from i ! = 0 ) toi = from i; i+; toi = 0 ; ,二、字符串指针作函数参数,47,(3) 形参用字符指针变量void copy_string ( char *from , char *to ) while( *from ! = 0
38、 ) *to = *from ; to+ ; from+ ; *to = 0 ; main ( ) char *a = “ I am a teacher .” ;char *b = “ you are a student .” ;printf(“str_a = %sn str_b = %sn”, a , b ) ;copy_string ( a , b ) ;printf(“n str_a=%sn str_b=%sn”, a , b );,二、字符串指针作函数参数,48,(4) 对 copy_string 函数的简化 void copy_string(char *from, char *to
39、) while ( (*to = *from ) ! = 0 ) from+ ; to+ ; 即先赋值,后判断, 故 *to = 0 语句不要 。 void copy_string (char *from, char *to ) while ( (*to+ = *from+ ) ! = 0 ) ; ,注意分号,二、字符串指针作函数参数,49, 由于表达式 (*to+ = *from+ ) != 0 等价于 (*to+ = *from+ ) != 0 void copy_string (char *from, char *to ) while ( (*to+ = *from+ ) != 0 )
40、; void copy_string ( char *from , char *to ) while ( *to+ = *from+ ) ; ,50,综上所述,用函数调用来处理字符串时,函数参数可以有以下几种情况:实参 形参1. 数 组 名 数 组 名2. 数 组 名 字符指针变量3. 字符指针变量 字符指针变量4. 字符指针变量 数 组 名,51,三、 字符指针变量与字符数组的区别1. 字符数组由若干个元素构成,每一个元素中存放 一个字符。而字符指针变量中存放的是字符串的首地址。绝非将字符串放在字符指针变量中。 2. 赋值方式可以不同。例如3. 数组定义后, 在编译时分配内存单元,即有确定的
41、值。对指针变量定义后,尽管系统给其分配了内存单元,但在没有明确指向前,其值不确定。例如4. 指针变量的值可以改变,而数组名则不行。例如,char str = “Hellow”;char *a = “ Hellow ” ; 以下对指针变量赋值操作合法:char *a ; a = “Hellow”; 以下对数组赋值操作不合法:char str10 ; str = “Hellow”;,char str = “Hellow”; 正确: char str10 ;scanf ( “ %s ”, str ) ; 错误: char *a ;scanf ( “ %s ”, a ) ; 可改为: char *a
42、, str10 ;a = str;scanf ( “ %s ”, a ) ;,例 9.21 (p240)main ( ) char *a=“I love China ! ” ;a = a + 7 ;printf ( “ %s ”, a ) ; 运行结果: China !,52,main ( ) char str = “ I love China ! ” ;str = str + 7 ;printf(“%s”, str) ;可改为: main ( ) char str = “ I love China ! ” ;printf(“%s”, str + 7 ) ;此时输出为: China !,不合法
43、,53,例 9.22 main ( ) char *a = “ I LOVE CHINA . ” ;int i ;printf(“The sixth character is %cn”, a5);for ( i = 0 ; ai ! = 0 ; i+ )printf(“%c”, ai) ;运行结果:The sixth character is EI LOVE CHINA .,指针变量带下标方式引 用字符等价于 *(a + i),54,5. 可用指针变量指向一个格式字符串,用以代替printf 函数中的格式控制。 如: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=%un”; 错误!printf ( format , c , d ) ; ,