本章导读指针是 C 语言中的一个重要的概念,也是 C 语言的一个重要特色。正确而灵活地运用它,可以有效地表示复杂的数据结构;能动态分配内存;
能方便地使用字符串;有效而方便地使用数组,能直接处理内存地址等,
这对设计系统件是很必要的。掌握指针的应用,可以使程序简洁、紧凑、
高效。每一个学习和使用 C 语言的人,都应当深入地学习和掌握指针。
可以说,不掌握指针就不掌握 C的精华。。
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本书目录第 6章 指针与引用本章主要知识点
(1) 关于指针的 C程序实例
(2) 指针
(3)指针与数组
(4) 指针与函数
(5) 多级指针与指针数组
(6) 内存管理
(7)引用第 6章 指针与引用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本章导读
6.2 指针
6.3 指针与数组
6.5 多级指针与指针数组
6.4 指针与函数
6.1 关于指针的 C程序实例
6.6 引用
6.7 内存管理
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本章目录
6.1.1 C程序实例
6.1 关于指针 的 C程序实例
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本节目录
2,C程序实例 (2)
1,C程序实例 (1)
6.1.1 C程序实例
6.1.1 C程序实例( 1)
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本节目录
1.C程序实例 1
【 例 6.1】 指针变量的定义示例。
/*程序名为 l5_1.cpp */
/*程序功能:验证指针变量的定义 */
main()
{ int num_int=12,*p_int; /*定义一个指向 int型数据的指针变量 p_int */
float num_f=3.14,*p_f; /*定义一个指向 float型数据的指针变量 p_f */
char num_ch=’p’,*p_ch; /*定义一个指向 char型数据的指针变量 p_ch */
p_int=&num_int; /*取变量 num_int的地址,赋值给 p_int */
p_f=&num_f; /*取变量 num_f的地址,赋值给 p_f */
p_ch=&num_ch; /*取变量 num_ch的地址,赋值给 p_ch */
printf(“num_int=%d,*p_int=%d\n”,num_int,*p_int);
printf(“num_f=%4.2f,*p_f=%4.2f\n”,num_f,*p_f);
printf(“num_ch=%c,*p_ch=%c\n”,num_ch,*p_ch);
}
程序运行结果:
num_int=12,*p_int=12
num_f=3.14,*p_f=3.14
num_ch=p,*p_ch=p
程序演示
[例 6.1]程序演示单击运行输入源程序弹出运行结果窗口返回例题 返回本节目录
6.1.1 C程序实例( 2)
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

2.C程序实例 2
【 例 6.2】 输入 2个整数,按升序(从小到大排序)输出。
/*程序名为 l5_2.cpp */
/*程序功能:使用指针变量求解 2个整数的升序输出 */
main()
{ int num1,num2;
int *num1_p=&num1,*num2_p=&num2,*pointer;
printf(“Input the first number:,);
scanf(“%d”,num1_p);
printf(“Input the second number:,);
scanf(“%d”,num2_p);
printf(“num1=%d,num2=%d\n”,num1,num2);
if( *num1_p > *num2_p ) /*如果 num1>num2,则交换指针 */
{ pointer= num1_p; num1_p= num2_p; num2_p=pointer; }
printf(“min=%d,max=%d\n”,*num1_p,*num2_p);
}
程序运行情况:
Input the first number:9<CR>
Input the second number:6<CR>
num1=9,num2=6
min=6,max=9 返回本节目录程序演示
[例 6.2]程序演示单击运行输入源程序弹出运行结果窗口返回例题 返回本节目录
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本章目录
6.2.2 指向变量的指针变量
6.2.1 地址和指针的概念
6.2 指针
6.2.1 地址和指针的概念
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

1.内存地址 ── 内存中存储单元的编号
2.变量地址 ── 系统分配给变量的内存单元的起始地址
( 1)计算机硬件系统的内存储器中,拥有大量的存储单元(每个存储单元容量为1字节)。
为了方便管理,必须为每一个存储单元编号,这个编号就是存储单元的“地址”。每个存储单元都有一个惟一的地址。
( 2)在地址所标识的存储单元中存放数据。
注意:内存单元的地址与内存单元中的数据是两个完全不同的概念 。
假设有这样一个程序:
main()
{ int num;
scanf("%d",&num);
printf("num=%d\n",num);
}
C编译程序编译到该变量定义语句时,将变量 num 登录到“符号表”中。符号表的关键属性有两个:一是“标识符名( id)”,二是该标识符在内存空间中的“地址( addr)” 。
为描述方便,假设系统分配给变量 num的 2字节存储单元为 3000 和 3001,则起始地址 3000就是变量 num在内存中的地址。 返回本节目录
6.2.1 地址和指针的概念
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

3.变量值的存取 ── 通过变量在内存中的地址进行系统执行,scanf(”%d“,&num);”和,printf(”num=%d\n“,num);”时,
存取变量 num值的方式可以有两种:
(1)直接访问 ──直接利用变量的地址进行存取上例中 scanf(“%d”,&num)的执行过程是这样的:
用变量名 num作为索引值,检索符号表,找到变量 num的起始地址 3000;然后将键盘输入的值(假设为3)送到内存单元 3000
和 3001中。
printf("num=%d\n",num)的执行过程,与 scanf( )很相似:
首先找到变量 num的起始地址 3000,然后从 3000和 3001中取出其值,最后将它输出。
返回本节目录
6.2.1 地址和指针的概念
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

( 2)间接访问 ──通过另一变量访问该变量的值
C语言规定:在程序中可以定义一种特殊的变量(称为指针变量),
用来存放其它变量的地址。
例如,假设定义了这样一个指针变量 num_pointer,它被分配到
4000,4001单元,其值可通过赋值语句,num_pointer=& num;”
得到。此时,指针变量 num_pointer的值就是变量 num在内存中的起始地址 3000。
【 例 5.2】 中 printf(“min=%d,max=%d\n”,*num1_p,*num2_p); 语句:通过指针变量,间接访问变量的值。
返回本节目录
6.2.2 指向变量的指针变量
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本节目录
1.指针与指针变量
( 1)指针 ──即地址一个变量的地址称为该变量的指针。通过变量的指针能够找到该变量。
( 2)指针变量 ──专门用于存储其它变量地址的变量指针变量 num_pointer的值就是变量 num的地址。指针与指针变量的区别,就是变量值与变量的区别。
( 3)为表示指针变量和它指向的变量之间的关系,用指针运算符,*”表示。
例如,指针变量 num_pointer与它所指向的变量 num的关系,表示为:
*num_pointer,即 *num_pointer等价于变量 num。
因此,下面两个语句的作用相同:
num=3; /*将 3直接赋给变量 num*/
num_pointer=&num; /*使 num_pointer指向 num */
*num_pointer=3; /*将 3赋给指针变量 num_pointer所指向的变量 */
6.2.2 指向变量的指针变量
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回 本节 目录
2.指针变量的定义与应用
【 例 6.1】 程序中头三行的变量定义语句 ──指针变量的定义与一般变量的定义相比,除变量名前多了一个星号,*” (指针变量的定义标识符)外,其余一样:
数据类型 *指针变量 [,*指针变量 2……];
注意:此时的指针变量 p_int,p_f,p_ch,并未指向某个具体的变量(称指针是悬空的)。使用悬空指针很容易破坏系统,导致系统瘫痪。
【 例 6.1】 中间三行的赋值语句 ──取地址运算 (& )
取地址运算的格式,&变量例如,&num_int,&num_f,&num_ch的结果,分别为变量 num_int,num_f、
num_ch的地址。
注意:指针变量只能存放指针(地址),且只能是相同类型变量的地址。
C语言中用 NULL表示空指针。若有语句:
p=NULL;
则表示指针 p为空,没有指向任何对象。
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本章目录
6.3.2 通过指针引用数组元素
6.3.1 指向数组元素的指针
6.3 指针与数组
6.3.3 数组名作函数参数
6.3.4 指针与字符数组
6.3.5 数组指针
6.3.1 指向数组元素的指针
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本节目录指向数组的元素指针变量的定义,与指向普通变量的指针变量的定义方法一样例如,int array[10]; ( 定义 array为包含 10个整型变量的数组 )
int *pointer (定义 pointer为指向整型变量的指针变量)
应当注意,如果数组为 int 型,则指针变量亦应指向 int 型。下面是对该指针赋值:
pointer= &array[0];
把 array[0] 元素的地址赋给指针变量 pointer。也就是说,pointer 指向 array数组的第 0
号元素。
C 语言规定数组名代表数组的首地址,也就是第一个元素的地址。因此,下面两个语句等价
pointer= &array[0];
pointer= array;
注意,数组名不代表整个数组,上述,pointer= array;”的作用是“把 array数组的第一个元素的地址赋给指针变量 pointer”而不是“把 array数组各元素的值赋给 pointer”。
6.3.2 通过指针引用数组元素
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本节目录
1 通过指针引用一维数组中的元素如果有,int array[10],*pointer=array;”,则:
( 1) pointer+i和 array+i都是数组元素 array[i]的地址。
( 2) *(pointer+i)和 *(array+i)就是数组元素 array[i]。
( 3)指向数组的指针变量,也可将其看作是数组名,
因而可按下标法来使用。例如,pointer[i]等价于
*(pointer+i)。
注意,pointer+1指向数组的下一个元素,而不是简单地使指针变量 pointer的值 +1。其实际变化为
pointer+1*size(size为一个元素占用的字节数)。
例如,假设指针变量 pointer的当前值为 3000,则
pointer+1为 3000+1*2=3002,而不是 3001。
6.3.2 通过指针引用数组元素
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本节目录
【 例 6.3】 使用指向数组的指针变量来引用数组元素。
/*程序名为 l6_3.cpp */
/*程序功能:使用指向数组的指针变量来引用数组元素 */
main()
{ int array[10],*pointer=array,i;
printf(“Input 10 numbers:,);
for(i=0; i<10; i++)
scanf(“%d”,pointer+i); /*使用指针变量来输入数组元素的值 */
printf(“array[10]:,);
for(i=0; i<10; i++)
printf(“%d,,*(pointer+i)); /*使用指向数组的指针变量输出数组 */
printf(“\n”);
}
6.3.2 通过指针引用数组元素
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本节目录程序运行情况:
Input 10 numbers,0 1 2 3 4 5 6 7 8 9<CR>
array[10],0 1 2 3 4 5 6 7 8 9
程序说明:
程序中第 3行和第 6行的 2个 for语句,等价于下面的程序段:
for(i=0; i<10; i++,pointer++)
scanf(“%d”,pointer);
printf(“array[10]:,);
pointer=array; /*使 pointer重新指向数组的第一个元素 */
for(i=0; i<10; i++,pointer++)
printf(“%d”,*pointer);
6.3.2 通过指针引用数组元素
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本节目录
2 通过指针引用 二 维数组中的元素在 C语言中,二维数组是按行优先的规律转换为一维线性存放在内存中的,因此,可以通过指针访问二维数组中的元素。
如果有,int a[M][N];
则将二维数组中的元素 a[i][j]转换为一维线性地址的一般公式是:
线性地址= a+ i× M+ j
其中,a为数组的首地址,M和 N分别为二维数组行和列的元素个数。
6.3.2 通过指针引用数组元素
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本节目录
【 例 6.4】,给定某年某月某日,将其转换成这一年的第几天并输出 。
此题的算法很简单,若给定的月是 i,则将 1,2,3,……,i-1月的各月天数累加,再加上指定的日 。 但对于闰年,二月的天数 29天,因此还要判定给定的年是否为闰年 。 为实现这一算法,需设置一张每月天数列表,给出每个月的天数,考虑闰年非闰年的情况,此表可设置成一个 2行 13列的二维数组,其中第 1行对应的每列 ( 设 1~ 12列有效 ) 元素是平年各月的天数,
第 2行对应的是闰年每月的天数 。 程序中使用指针作为函数 day_of_year的形式参数 。
/*程序名为 l6_4.cpp */
/*程序功能:使用指向数组的指针变量来引用数组元素 */
#include <stdio.h>
main( )
{ static int day_tab[2][13]={
{0,31,28,31,30,31,30,31,31,30,31,30,31},
{0,31,29,31,30,31,30,31,31,30,31,30,31} };
int y,m,d;
scanf("%d%d%d",&y,&m,&d);
6.3.2 通过指针引用数组元素
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本节目录
printf("%d\n",day_of_year(day_tab,y,m,d) ); /* 实参为二维数组名 */
}
day_of_year(day_tab,year,month,day)
int *day_tab; /* 形式参数为指针 */
int year,month,day;
{ int i,j;
i = (year%4==0&&year%100!=0) || year%400==0;
for ( j=1; j<month; j++ )
day += *( day_tab+i*13+j );
/* day_tab+i*13+j:对二维数组中元素进行地址变换 */
return(day);
}
由于C语言对于二维数组中的元素在内存中是按行存放的,所以在函数 day_of_year 中要使用公式 "day_tab+i*13+j"计算 main函数的 day_tab中元素对应的地址 。
6.3.3 数组名作函数参数
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本节目录数组名可以用作函数的形参和实参。 如:
main ( )

int array[10] ;
f ( array,10 )
}
f ( arr,n )
int arr[ ],n ;
{
}
array 为实参数组名,arr 为形参数组名。
6.3.3 数组名作函数参数
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本节目录
【 例 6.5】 将数组 a 中 n 个整数按相反顺序存放解此题的算法为:将 a [0]与 a[n-1 ]对换,再将 a[1]与 a[n-2]对换,… …,直到将 a[(n-1)/2] 与 a [n-int((n-1)/2)] 对换。今用循环处理此问题,设两个“位置指示变量” i 和 j,i 的初值为 0,j 的初值为 n-1。将
a[i]与 a[j] 交换,然后使 i 的值加 1,j 的值减 1,再将 a[i]与 a[j]对换,直到 i =(n-1)/2 为止。
程序如下:程序名为 l6_5.cpp
Void inv(int x[],int n) /*形参 x是数组名 */
{
int temp,i,j,m=(n-1)/2;
for(i=0;i<=m;i++)
{j=n-1-i;
temp=x[i];x[iI]=x[j];x[j]=temp;}
return;
}
main()
{ int i,a[10]={3,7,9,11,0,6,7,5,4,2};
for(i=0;i<10;i++)
6.3.3 数组名作函数参数
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本节目录
printf(“%d,”,a[i]);
printf(“\n”);
inv(a,10);
for(i=0;i<10;i++)
printf(“%d,”,a[i]);
printf(“\n”);
}
运行情况如下:
3,8,11,0,5,9,4,7,10,2,<CR>
2,10,7,4,9,5,0,11,8,3,
程序说明:
主函数中数组名为 a,赋以各元素初值。函数 inv 中的形参数组名为 x,在 inv 函数中不具体定义数组元素的个数,元素个数由形参变量 n 传入(今对应的实参值为 10 )。这样做可以增加函数的灵活性。即不必要求函数 inv 中的形参数组
x 和 main 函数中的实参数组 a 长度相同。如果在 main函数中有函数调用语句:
,inv ( a,10 )”,表示要求对 a 数组的前 10 个元素实行题目要求的颠倒排列。
如果改为,inv ( a,5 )”,则表示将 a 数组的前 5 个元素实行颠倒排列,此时,
函数 inv 只处理 5 个数组元素。函数 inv 中的 m 是 i 值的上限,当 i <m时,循环继续执行,当 i > m 时,则结束循环过程。
6.3.3 数组名作函数参数
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本节目录小结,
引入指向数组的指针变量后,数组及指向数组的指针变量作函数参数时,可有4种等价形式(本质上是一种,即指针数据作函数参数):
( 1)形参、实参都用数组名
( 2)形参、实参都用指针变量
( 3)形参用指针变量、实参用数组名
( 4)形参用数组名、实参用指针变量
6.3.4 指针与字符数组
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本节目录
1,字符串的表示与引用在C语言中,既可以用字符数组表示字符串,也可用字符指针变量来表示;
引用时,既可以逐个字符引用,也可以整体引用。
(1)逐个引用
【 例 6.6】 使用字符指针变量表示和引用字符串。
/*程序名为 l6_6.cpp /
main()
{ char *string=”I love Beijing.”;
for(; *string!=’\0’; string++) printf(“%c”,*string);
printf(“\n”);
}
程序运行结果:
I love Beijing.
程序说明,char *string="I love Beijing.";
语句定义并初始化字符指针变量 string:用串常量,I love Beijing.”的地址
(由系统自动开辟、存储串常量的内存块的首地址)给 string赋初值。
6.3.4 指针与字符数组
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本节目录
(2)整体引用
【 例 6.7】 采取整体引用的办法,改写 [例 5.9]。
/*程序名为 l6_7.cpp */
/*程序功能:使用字符指针变量表示和引用字符串 */
main()
{
char *string=”I love Beijing.”;
printf(“%s\n”,string);
}
程序说明,printf(“%s\n”,string);语句通过指向字符串的指针变量 string,整体引用它所指向的字符串的原理:
系统首先输出 string指向的第一个字符,然后使 string自动加1,使之指向下一个字符;重复上述过程,直至遇到字符串结束标志。
注意,其它类型的数组,是不能用数组名来一次性输出它的全部元素的,
只能逐个元素输出。
6.3.4 指针与字符数组
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本节目录
2.字符指针变量与字符数组之比较虽然用字符指针变量和字符数组都能实现字符串的存储和处理,但二者是有区别的,不能混为一谈。
( 1)存储内容不同。
字符指针变量中存储的是字符串的首地址,而字符数组中存储的是字符串本身(数组的每个元素存放一个字符)。
( 2)赋值方式不同。
对字符指针变量,可采用下面的赋值语句赋值:
char *pointer;
pointer="This is a example.";
而字符数组,虽然可以在定义时初始化,但不能用赋值语句整体赋值。下面的用法是非法的:
char char_array[20];
char_array="This is a example."; /*非法用法 */
( 3)指针变量的值是可以改变的,字符指针变量也不例外;
6.3.4 指针与字符数组
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本节目录
3,字符串指针作函数参数
【 例 6.8】 用函数调用方式,实现字符串的复制。
/*程序名为 l6_8.cpp */
/**********************************************************/
/*string_copy()函数:复制一个字符串 */
/*形参:字符指针 str_from接收源串,字符指针 str_to存储目标串 */
/*返回值:无 */
/**********************************************************/
void string_copy(char *str_from,char *str_to)
{ int i=0;
for(; (*(str_to+i)=*(str_from+i))!=’\0’; i++) ; /*循环体为空语句 */
}
main()
{ char array_str1[20]=”I am a teacher.”;
char array_str2[20];
6.3.4 指针与字符数组
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本节目录
string_copy(array_str1,array_str2) ; /*数组名作实参 */
printf(“array_str2=%s\n”,array_str2);
}
程序运行结果:
I am a teacher.
程序说明:
for(; (*(str_to+i)=*(str_from+i))!=’\0’; i++) ; 语句的执行过程为:
首先将源串中的当前字符,复制到目标串中;然后判断该字符
(即赋值表达式的值)是否是结束标志。如果不是,则相对位置变量 i的值增 1,以便复制下一个字符;如果是结束标志,则结束循环。其特点是:先复制、后判断,循环结束前,结束标志已经复制。
6.3.5 数组指针
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本节目录我们上面介绍的指针都是指向某一类型的变量的,例如可以使一个指针 p指向某一数组元素。如果 p的值加 1,则指向下一个元素,这样指针在处理一维数组时非常方便,但在处理二维数组时就不适合了。
如果定义一个指针 p,让它指向一个包含 n个元素的一维数组,且 p的增值以一维数组的长度为单位,此时,如果指针 P指向二维数组的某一行,
则 p+1就指向了该二维数组的下一行。在 C++中,这样的指针被称为数组指针,使用数组指针可以很方便地处理二维数组。
数组指针的说明形式如下:
存储类型 数据类型 (*指针名 )[元素个数 ]
例如,在程序中定义一个数组指针:
int (*p)[4];
它表明指针 p指向的数组指针 p指向一个一维数组,p的值就是该一维数组的首地址。
在使用数组指针时,有两点一定要注意:
(1) *p两侧的括号一定不要漏掉,如果写成 *p[4]的形式,由于 [ ]的运算级别高,因此 p先和 [4]结合,是数组,然后再与前面的 *结合,*p[4]是指针数组。
6.3.5 数组指针
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本节目录
(2) p是一个行指针,它只能指向一个包含 n个元素的一维数组,不能指向一维数组中的元素。
【 例 6.9】,用数组指针处理二维数组。
程序名为 l6_9.cpp
main()
{
int a[2][3]={1,3,5,7,9,11};
int (*p)[3];
int i,j;
p=a;
for(i=0;i<2;i++)
{ for(j=0;j<3;j++)
printf(“%2d”,(*p)[j]);
p++;
}}
程序运行结果为:
1 3 5 7 9 11
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本章目录
6.4.2 函数指针
6.4.3 指针函数
6.4.1 指针作函数参数
6.4 指针与函数
6.4.1 指针作函数参数
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回 本节 目录
1.指针变量,既可以作为函数的形参,也可以作函数的实参。
2.指针变量作实参时,与普通变量一样,
也是,值传递,,即将指针变量的值
(一个地址)传递给被调用函数的形参
(必须是一个指针变量)。
注意:被调用函数不能改变实参指针变量的值,但可以改变实参指针变量所指向的变量的值。
6.4.1 指针作函数参数
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回 本节 目录
【 例 6.10】 使用函数调用方式改写例 6.2,要求实参为指针变量。
/*程序名为 l6_10.cpp /
/******************************************************/
/*exchange()功能:交换 2个形参指针变量所指向的变量的值 */
/*形参,2个,均为指向整型数据的指针变量 */
/*返回值:无 */
/******************************************************/
void exchange(int *pointer1,int *pointer2)
{ int temp;
temp=*pointer1,*pointer1=*pointer2,*pointer2=temp;
}
/*主函数 main()*/
main()
{ int num1,num2; /*定义并初始化指针变量 num1_p和 num2_p */
int *num1_p=&num1,*num2_p=&num2;
printf(“Input the first number:,); scanf(“%d”,num1_p);
printf(“Input the second number:,);
6.4.1 指针作函数参数
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回 本节 目录
scanf(“%d”,num2_p);
printf(“num1=%d,num2=%d\n”,num1,num2);
if( *num1_p > *num2_p ) /* 即 num1>num2)*/
exchange(num1_p,num2_p); /*指针变量作实参 */
printf(“min=%d,max=%d\n”,num1,num2); /*输出排序后的 num1和 num2
的值 */
}
程序运行情况:
Input the first number:9<CR>
Input the second number:6<CR>
num1=9,num2=6
min=6,max=9
程序说明:
形参指针变量 pointer1(指向变量 num1)和 pointer2(指向变量 num2),在函数调用开始时才分配存储空间,函数调用结束后立即被释放。
虽然被调用函数不能改变实参指针变量的值,但可以改变它们所指向的变量的值。
6.4.2 函数指针
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回 本节 目录
1.函数指针的概念一个函数在编译时,被分配了一个入口地址,这个地址就称为该 函数的指针 。
可以用一个指针变量指向一个函数,然后通过该指针变量调用此函数。
【 例 6.11】,求 a 和 b中的大者。
程序名为 l6_11.cpp
main ( )
{
int max( );
int (*p)( );
int a,b,c;
p=max;
scanf ("%d,%d”,&a,&b);
6.4.2 函数指针
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回 本节 目录
c=(*p) (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)}
程序说明:
其中 int (*p)( )说明 p 是一个指向函数的指针变量,此函数带回整型的返回值。注意 *p 两侧的括弧不可省略,表示 p 先与 *结合,是指针变量,
然后再与后面的()结合,表示此指针变量指向函数,这个函数值
(即函数返回的值)是整型的。如果写成,int *p”,则由于()优先级高于 *,它就成了说明一个函数了,这个函数的返回值是指向整型变量的指针。
6.4.2 函数指针
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回 本节 目录
2.指向函数的指针变量
( 1)定义格式函数类型 (*指针变量 )( );
注意:,*指针变量”外的括号不能缺,否则成了返回指针值的函数。
例如,int (*fp)(); /* fp为指向 int函数的指针变量 */
( 2)赋值函数名代表该函数的入口地址。因此,可用函数名给指向函数的指针变量赋值。
指向函数的指针变量= [&]函数名 ;
注意,函数名后不能带括号和参数;函数名前的,&”符号是可选的。
(3)调用格式
(*函数指针变量 )([实参表 ])
(4) 函数名作实参时,因为要缺省括号和参数,造成编译器无法判断它是一个变量还是一个函数,所以必须加以说明。
(5) 注意:对指向函数的指针变量,诸如 p+i,p++/p--等运算是没有意义的。
6.4.2 函数指针
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回 本节 目录
3.指向函数的指针变量作函数参数指向函数的指针变量的常用用途之一,就是将函数指针作参数,传递到其它函数。
【 例 6.12】,设一个函数 process,在调用它的时候,每次实现不同的功能。
输入 a 和 b 两个数,第一次调用 process时找出 a 和 b 中大者,第二次找出其中小者,第三次求 a 与 b 之和。程序如下:
程序名为 l6_12.cpp
main()
{
int max(int,int); /*函数声明 */
int min(int,int); /*函数声明 */
int add(int,int); /*函数声明 */
int a,b;
scanf(“%d,%d”,&a,&b);
printf(“max=”);
6.4.2 函数指针
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回 本节 目录
process(a,b,max);
printf(“min=”);
process(a,b,min);
printf(“sum=”);
process(a,b,add);
}
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;
6.4.2 函数指针
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回 本节 目录
else z=y;
return(z);
}
add(int x,int y) /*函数定义 */
{
int z;
z=x+y;
return(z);
}
process(int x,int y,int(*fun)(int,int)) 函数定义,int(*fun)(int,int)表示 fun是指向 */
/*函数的指针,该函数是一个整型函数,有两个整型形参,*/
{
int result;
result=(*fun)(x,y);
printf(%d\n”,result);
}
6.4.2 函数指针
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回 本节 目录程序运行结果如下:
3,9<CR>
max=9
min=3
sum=12
程序说明,
max,min 和 sum 是已定义的三个函数,分别用来实现求大数、求小数和求和的功能。在 main 函数中第一次调用 process函数时,除了将 a 和 b
作为实参将两个数传给 process的形参 x,y 外,还将函数名 max作为实参将其入口地址传送给 process函数中的形参 ----指向函数的指针变量
fun,这时,process函数中的 (*fun) ( x,y ) 相当于 max ( x,y ),执行
process可以输出 a 和 b 中大者。在 main函数第二次调用时,改以函数名
min 作实参,此时 process函数的形参 fun 指向函数 min,在 process函数中的函数调用 (*fun) ( x,y )相当于 min ( x,y )。同理,第三次调用
process函数时,(*fun) ( x,y )相当于 add ( x,y )。从本例可以清楚地看到,不论执行 max,min或 add,函数 process 一点都没有改动,只是在调用 process函数时实参函数名改变而已。这就增加了函数使用的灵活性。
6.4.3 指针函数
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回 本节 目录指针函数是指返回值为指针的函数,函数的返回值可以是不同类型的指针指针函数定义格式如下:
函数类型 *函数名 ([形参表 ])
例如,int *pr(x,y);
pr是函数名,调用它以后能得到一个指向整型数据的指针(地址)。 x,y 是函数 pr 的形参。请注意在 *pr
两侧没有括弧,在 pr的两侧分别为 *运算符和()运算符。而()优先级高于 *,因此 a 先与()结合。显然这是函数形式。这个函数前面有一个 *,表示此函数是指针型函数(函数值是指针)。最前面的 int 表示返回的指针指向整型变量。
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本章目录
6.5.2 指针数组
6.5.3 main函数的参数
6.5.1 多级指针
6.5 多级指针与指针数组
6.5.1 多级指针
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

1.概念在前面的叙述中,一个指针变量可以指向一个相应数据类型的数据,例如:
int a,*p;
p=&a;
使指针 p指向 a,则指针 p所指向的变量 *p就是要处理的数据变量 a.如果同时存在另一个指针 pp,并且把指针 p的地址赋予指针变量 pp,即:
pp=&p;
则 pp就指向指针 p,这时指针 pp所指向的变量 *pp就是指针 p。在 C++中,
把 pp这样的指向指针的指针称为多级指针。
返回 本节 目录
2.定义格式数据类型 **指针变量 [,**指针变量 2……] ;
6.5.1 多级指针
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回 本节 目录
【 例 6.13】 用二级指针处理多个字符串。
程序名为 l6_13.cpp
main ( )
{
static char * name[ ]= {"Follow me","BASIC","FORTRAN","Great
Wall","Computerdesign"};
char * * p;
int i;
for(i=0;i<5;i++)
{ p=name+i;
printf(“%s\n”,*p); }
}
}
程序运行结果,
Follow me
BASIC
FORTRAN
Great Wall
Computerdesign
6.5.1 多级指针
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回 本节 目录程序说明:
指针数组的元素也可以不指向字符串,而指向整型数据或实型数据等,例如:
int a[5]={l,3,5,7,9 },
int *num[5]={&a[0],&a[l],&a[2],&a[3],&a[4};
int * * p ;
此时为了得到数据,5 ",可以先使 p =num + 2,然后输出 ** p 。注意 *p 是 p 间接指向的对象的地址。而
**p 是 p 间接指向的对象的值。
6.5.2 指针数组
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

1.概念
2.定义格式数组的每个元素都是一个指针数据。
数据类型 *数组名 [元素个数 ]
指针数组常适用于指向若干字符串,这样使字符串处理更加灵活方便。
返回 本节 目录
6.5.3 main函数的参数
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本节目录指针数组的一个重要应用是作为 main函数的形参。在前面讲述的程序中,main函数的第一行全部写成了以下形式:
main ( )
括号中为空,表示没有参数。实际上 main函数是可以带参数的,
其一般形式为:
main (argc,argv)
int argc; /* argc表示命令行参数个数 */
char *argv[ ]; /* argv指向命令行参数的指针数组 */
argc和 argv是 main函数的形式参数。
在操作系统下运行C程序时,可以以命令行参数形式,向 main函数传递参数。命令行参数的一般形式是:
运行文件名 参数 1 参数 2 …… 参数 n
运行文件名和参数之间、各个参数之间要用一个空格分隔。
argc表示命令行参数个数(包括运行文件名),argv是指向命令行参数的数组指针。指针 argv[0]指向的字符串是运行文件名,argv[1]
指向的字符串是命令行参数 1,argv[2] 指向的字符串是命令行参数
2,……,等等。
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本章目录
6.6.1 引用
6.6 引用
6.6.1 引用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

1.概念
“引用” ( reference )是 C + +的一种新的变量类型,是对 C 的一个重要扩充。它的作用是为一个变量起一个别名。
假如有一个变量 a,想给它起一个别名 b,
可以这样写,int a ;
int &b= a ;
这就声明了 b 是 a 的“引用”,即 a 的别名。经过这样的声明后,使用 a 或 b 的作用相同,都代表同一变量。注意:在上述声明中,&是“引用声明符”,并不代表地址。不要理解为“把 a 的值赋给 b 的地址”。声明引用并不另开辟内存单元,b 和 a 都代表同一变量单元。在声明一个引用型变量时,必须同时使之初始化,
即声明它代表哪一个变量。
返回 本节 目录
6.6.1 引用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

2,引用的简单使用通过下面的例子可以了解引用的简单使用。
【 例 6.14】,了解引用和变量的关系。
程序名为 l6_14.cpp
# include <Ciostream,h>
tt include <iomanip,h>
void main( )
{
int a = 10;
int &b = a; //声明 b 是 a 的引用 //
a = a * a; //a 的值变化了,b 的值也应一起变化 //
cout <<a<<setw(6)<<b;
b = b/5; // b 的值变化了,a 的值也应一起变化 //
cout<<b<<setw(6)<<a; } 返回 本节 目录
6.6.1 引用
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

程序说明:
a 的值开始为 10,b 是 a 的引用,它的值当然也应该是 10,当 a
的值变为 100 ( a * a 的值)时,b 的值也随之变为 100 。在输出 a
和 b 的值后,b 的值变为 20,显然 a 的值也应为 20 。
运行结果如下:
100 100
20 20
返回 本节 目录
3,引用作为函数参数有了变量名,为什么还需要一个别名呢? C 十+之所以增加
,引用,,主要是把它作为函数参数,以扩充函数传递数据的功能。
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

返回本章目录
6.7.1内存管理
6.7内存管理
6.7.1内存管理
《C
语言程序设计
,(V
isu
al
C+
+
6.
0
环境

C + +提供了较简便而功能较强的运算符 new 和 delete 来获得和释放内存。
new 运算符使用的一般格式为
new 类型 [初值 ]
用 new 分配数组空间时不能指定初值。
delete 运算符使用的一般格式为
delete [] 指针变量在使用 new和 delete 运算符时,应注意以下几点:
① 用 new获取的内存空间,必须用 delete 进行释放;
② 对一个指针只能调用一次 delete ;
③ 用 delete 运算符作用的对象必须是用 new 分配的内存空间的首地址。
④ 如果由于内存不足等原因而无法正常分配空间,则 new 会返回一个空指针 NULL,用户可以根据该指针的值判断分配空间是否成功。
⑤ new 和 delete 是运算符,不是函数,因此执行效率高。
返回 本节 目录