📄 tc11.dat
字号:
指向数组的指针变量的定义,与指向普通变量的指针变量的定义方法一样.
例如,int array[10], *pointer=array(或&array[0]);
或者:
int array[10], *pointer;
pointer=array;
注意:数组名代表数组在内存中的起始地址(与第1个元素的地址相同),所以可以用数组名给指针变量赋值.
3.数组元素的引用
数组元素的引用,既可用下标法,也可用指针法.使用下标法,直观;而使用指针法,能使目标程序占用内存少、运行速度快.
9.3.2 通过指针引用数组元素
如果有“int array[10],*pointer=array;” ,则:
(1)pointer+i和array+i都是数组元素array[i]的地址,如图9-6所示.
(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.
[案例9.5] 使用指向数组的指针变量来引用数组元素.
/*案例代码文件名:AL9_5.C*/
/*程序功能:使用指向数组的指针变量来引用数组元素*/
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”);
} [程序演示]
程序运行情况:
Input 10 numbers: 0 1 2 3 4 5 6 7 8 9←┘
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);
思考题:
(1)如果去掉“pointer=array;”行,程序运行结果会如何?请上机验证.
(2)在本案例中,也可以不使用i来作循环控制变量,程序怎么修改?提示:指针可以参与关系运算.
说明:
(1)指针变量的值是可以改变的,所以必须注意其当前值,否则容易出错.
(2)指向数组的指针变量,可以指向数组以后的内存单元,虽然没有实际意义.
(3)对指向数组的指针变量(px和py)进行算术运算和关系运算的含义
1)可以进行的算术运算,只有以下几种:
px±n, px++/++px, px--/--px, px-py
·px±n:将指针从当前位置向前(+n)或回退(-n)n个数据单位,而不是n个字节.显然,px++/++px和px--/--px是px±n的特例(n=1).
·px-py:两指针之间的数据个数,而不是指针的地址之差.
2)关系运算
表示两个指针所指地址之间、位置的前后关系:前者为小,后者为大.
例如,如果指针px所指地址在指针py所指地址之前,则px〈py的值为1.
9.3.3 再论数组作函数参数
数组名作形参时,接收实参数组的起始地址;作实参时,将数组的起始地址传递给形参数组.
引入指向数组的指针变量后,数组及指向数组的指针变量作函数参数时,可有4种等价形式(本质上是一种,即指针数据作函数参数):
(1)形参、实参都用数组名
(2)形参、实参都用指针变量
(3)形参用指针变量、实参用数组名
(4)形参用数组名、实参用指针变量
9.3.4 2维数组的指针及其指针变量
1. 2维数组的指针
假设有如下数组定义语句: int array[3][4];
(1)从2维数组角度看,数组名array代表数组的起始地址, 是一个以行为单位进行控制的行指针:
·array+i:行指针值,指向2维数组的第i行.
·*(array+i):(列)指针值,指向第i行第0列(控制由行转为列,但仍为指针).
·*(*(array+i)):数组元素array[i][0]的值.
用array作指针访问数组元素array[i][j]的格式:
*(*(array+i)+j)
注意:行指针是一个2级指针,如图9-7所示.
(2)从1维数组角度看,数组名array和第1维下标的每一个值, 共同构成一组新的1维数组名array[0]、array[1]、array[2],它们均由4个元素组成.
C语言规定:数组名代表数组的地址,所以array[i]是第i行1维数组的地址, 它指向该行的第0列元素,是一个以数组元素为单位进行控制的列指针:
·array[i]+j:(列)指针值,指向数组元素array[i][j].
·*(array[i]+j):数组元素array[i][j]的值.
如果有“int array[3][4],*p=array[0];”,则p+1指向下一个元素,如图9-8所示.
用p作指针访问数组元素array[i][j]的格式:
*(p+(i*每行列数+j) )
2.行指针变量──指向由n个元素组成的一维数组的指针变量
(1)定义格式
数据类型 (*指针变量)[n];
注意:“*指针变量”外的括号不能缺,否则成了指针数组--数组的每个元素都是一个指针──指针数组(本章第6节介绍).
(2)赋值
行指针变量 = 2维数组名 | 行指针变量;
[案例9.6] 使用行指针和列指针两种方式输出2维数组的任一元素.
(1) 使用行指针
/*案例代码文件名:AL9_6_1.C*/
/*程序功能:使用行指针输出2维数组的任一元素*/
main()
{ int array[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int (*pointer)[4], row, col;
pointer=array;
printf(“Input row = ”); scanf(“%d”, &row);
printf(“Input col = ”); scanf(“%d”, &col);
printf(“array[%1d][%1d] = %d\n”, row, col, *(*(pointer+row)+col));
} [程序演示]
程序运行情况:
Input row = 1←┘
Input col = 2←┘
array[1][2] = 7
思考题:本题也可以直接使用数组名array作指针,应如何修改?
(2)使用列指针
/*案例代码文件名:AL9_6_2.C*/
/*程序功能:使用列指针输出2维数组的任一元素*/
main()
{ int array[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int *pointer, row, col; /*定义一个(列)指针变量pointer*/
pointer=array[0]; /*给(列)指针变量pointer赋值*/
printf(“Input row = ”); scanf(“%d”,&row);
printf(“Input col = ”); scanf(“%d”,&col);
printf(“array[%1d][%1d] = %d\n”, row, col, *(pointer+(row*4+col)));
} [程序演示]
3. 2维数组指针作函数参数
2维数组的指针作函数实参时,有列指针和行指针两种形式.相应的,用来接受实参数组指针的形参,必须使用相应形式的指针变量,如下所示:
实参: 列指针 行指针
↓ ↓
形参: (列)指针变量 行指针变量
9.3.5 动态数组的实现
在程序运行过程中,数组的大小是不能改变的.这种数组称为静态数组.静态数组的缺点是:对于事先无法准确估计数据量的情况,无法做到既满足处理需要,又不浪费内存空间.
所谓动态数组是指,在程序运行过程中,根据实际需要指定数组的大小.
在C语言中,可利用内存的申请和释放库函数,以及指向数组的指针变量可当数组名使用的特点,来实现动态数组.
动态数组的本质是:一个指向数组的指针变量.
[案例9.7] 动态数组的实现.
/*案例代码文件名:AL9_7.C*/
/*程序功能:实现动态数组*/
#include “alloc.h”
#include “stdlib.h”
main()
{ int *array=NULL, num, i;
printf(“Input the number of element: ”); scanf(“%d”, &num);
/*申请动态数组使用的内存块*/
array=(int *)malloc( sizeof(int) * num );
if ( array==NULL ) /*内存申请失败:提示,退出*/
{ printf(“out of memory, press any key to quit……”);
exit(0); /*exit():终止程序运行,返回操作系统*/
}
/*提示输入num个数据*/
printf(“Input %d elements: ”, num);
for (i=0; i<num; i++) scanf(“%d”, &array[i]);
/*输出刚输入的num个数据*/
printf(“%d elements are: ”, num);
for (i=0; i<num; i++) printf(“%d,”, array[i]);
printf(“\b ”); /*删除最后一个数据后的分隔符“,”*/
free(array); /*释放由malloc()函数申请的内存块*/
} [程序演示]
程序运行情况:
Input the number of element: 3←┘
Input 3 elements: 1 2 3←┘
3 elements are: 1,2,3
程序说明:
(1) array=(int *)malloc( sizeof(int) * num );语句──malloc()函数和sizeof运算符
1)库函数malloc()
·用法:void *malloc(unsigned size)
·功能:在内存的动态存储区分配1个长度为size的连续空间.
·返回值:申请成功,则返回新分配内存块的起始地址;否则,返回NULL.
·函数原型:alloc.h,stdlib.h.
malloc()函数的返回值是一个无类型指针,其特点是可以指向任何类型的数据.但在实际使用malloc()函数时,必须将其返回值强制转换成被赋值指针变量的数据类型,以免出错.
2)运算符sizeof
·格式:sizeof(变量名/类型名)
·功能:求变量/类型占用的内存字节数(正整数).例如,在IBM-PC机上,sizeof(int)=2.
思考题:在该语句中,使用sizeof(int)求出1个int型数据占用的内存字节数,而不是使用常量“2”,为什么?
(2) scanf(“%d”, &array[i]);语句和printf(“%d,”, array[i]);语句
将指向数组的指针变量当作数组名使用,所以就必须按引用数组元素的语法规则来使用.
(3) printf(“\b ”);语句
“\b” 在该语句中的作用是,使光标定位到最后一个数据后的分隔符“,”上,然后再输出一个空格,以达到删除之目的.
(4) free(array);语句──库函数free()
·用法:void free(void *ptr)
·功能:释放由ptr指向的内存块(ptr是调用malloc() 函数的返回值).
·返回值:无.
·函数原型:stdlib.h,alloc.h.
原则上,使用malloc()函数申请的内存块,操作结束后,应及时使用free()函数予以释放.尤其是循环使用malloc()函数时,如果不及时释放不再使用的内存块,很可能很快就耗尽系统的内存资源,从而导致程序无法继续运行.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -