5- 灵活使用指针_第1页
5- 灵活使用指针_第2页
5- 灵活使用指针_第3页
5- 灵活使用指针_第4页
5- 灵活使用指针_第5页
已阅读5页,还剩51页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

教学内容: 第1章:C语言语法基础第2章:C程序设计基础第3章:利用数组处理同类型的批量数据第4章:利用函数实现模块化程序设计第5章:灵活使用指针第6章:结构体、共用体、枚举类型及其应用第7章:常用的三种线性数据结构第8章:利用文件进行数据管理第9章:嵌入式技术基础实践方法C语言程序设计5.1指针的基本概念5.2指向普通变量的指针5.3指向数组的指针5.4指向字符串的指针5.5指向函数的指针5.6返回指针值的函数5.7指针数组、指向指针的指针5.8内存动态分配与指向动态内存区的指针变量5.9指针小结 【学习内容】

第5章灵活使用指针第5章灵活使用指针指针1.理解指针的概念;2.掌握指向普通变量的指针及应用;3.掌握指向数组的指针及应用;4.掌握指向字符串的指针及应用;5.掌握指向函数的指针及应用;6.掌握返回指针值的函数及应用;7.掌握指针数组和指向指针的指针及应用;8.掌握内存动态分配函数的使用方法。【学习目标】

5.1指针的基本概念

对变量值的存、取都是通过变量的地址进行的。

例如,scanf("%d",&i);将键盘上输入的数据送给变量i对应的地址单元中。

再如,

printf("%d",i);从变量i对应的地址单元中取出变量i的值。

直接按照变量名(对应一个内存地址)进行的访问,称为“直接访问”方式。

除了采用“直接访问”方式,还可以采用“间接访问”方式。

可通过语句“p=&i;”将变量i的地址(2000)存放到变量p中(变量p的值就是2000)。

要读取变量i的值,可以先找到变量p,从中取出i的地址(2000),然后到地址为2000的内存单元取出i的值(3)。

通过变量p能够找到变量i,可以说变量p指向了变量i,在C语言中,将地址形象地称为“指针”。

一个变量的地址,称为该变量的“指针”。例如,地址2000是变量i的指针,而变量p用来存放变量i的地址,称为“指针变量”。5.2指向普通变量的指针

5.2.1定义指针变量的方法

定义指针变量的一般形式:类型标识符*变量名;

例如:

int*p1;//p1是指向整型变量的指针变量

注意:一个指针变量只能指向同类型的变量,如p2只能指向实型变量,不能指向字符变量。float*p2;

//p2是指向实型变量的指针变量char*p3;

//p3是指向字符变量的指针变量

所谓普通变量,是指基本数据类型(整型、实型、字符型)的变量。

变量的指针就是变量的地址。存放变量地址的变量是指针变量,用来指向另一个变量。5.2指向普通变量的指针

5.2.2指针变量的引用请牢记:指针变量中只能存放地址(指针)。

两个有关的运算符:(1)&:取地址运算符。(2)*:指针运算符(或称“间接访问”运算符),取其指向单元的内容。

例如,&a表示变量a的地址,*p表示指针变量p所指向的存储单元的内容(即p所指向的变量的值)。5.2指向普通变量的指针

【例5.1】通过指针变量访问整型变量。5.2.2指针变量的引用#include<stdio.h>intmain(void){ inta=10,b=20;

int*p1,*p2;

//定义两个指针变量,均指向整型变量

p1=&a;

//取变量a的地址,赋给指针变量p1

p2=&b;

//取变量b的地址,赋给指针变量p2printf("a=%d,b=%d\n",a,

b);printf("a=%d,b=%d\n",

*p1,*p2);//输出指针变量指向单元的内容printf("变量a的地址:%x\n",p1);//输出变量a的地址printf("变量b的地址:%x\n",p2);//输出变量b的地址}5.2指向普通变量的指针

inta;int*p;p=&a;inta;int*p=&a;

(1)等价。与说明:(2)不能直接将一个地址常数赋给一个指针变量,只有强制类型转换后才能赋值:int*p=0x12345600;//错误int*p=(int*)0x12345600;//正确

(3)注意“*p”在定义和引用中的区别:定义时:*p的前面要有类型标识符,表示指针变量p是指向某种类型数据的;引用时:*p的前面没有类型标识符,表示指针变量p所指向的存储单元的内容。5.2.2指针变量的引用5.2指向普通变量的指针

5.2.2指针变量的引用(4)inta; int*p=&a;则&*p和*&a的含义分别是什么?②*&a:先执行&a,表示变量a的地址,也就是变量p,再执行*运算。因此*&a与*p等价,即变量a。“&”和“*”优先级相同,并按“自右至左”的结合性。①&*p:先执行*p,表示变量a,再执行&运算。因此&*p与&a相同,即变量a的地址(p)。说明:5.2指向普通变量的指针

5.2.2指针变量的引用【例5.2】指针变量的应用:输入两个整数,按由大到小的顺序输出这两个整数。#include<stdio.h>intmain(void){ inta,b;

int*p1,*p2,*p;printf("请输入两个整数(用空格间隔):");scanf("%d%d",&a,

&b);

p1=&a;p2=&b;if(a<b) {

p=p1;p1=p2;p2=p;

//交换指针变量的指向}printf("由大到小:%d,%d\n",*p1,*p2);}5.2指向普通变量的指针

5.2.3指针变量作为函数参数【例5.3】指针变量(变量的地址)作为函数参数。实参指针的指向

实参传递给形参

变量a和b的值都加1形参被释放

指针变量作函数参数,其作用是将一个变量的地址传递到另一个函数中。#include<stdio.h>voidfun(int*p1,int*p2);

//函数声明intmain(void){ inta=1,b=5;

int*pa=&a,*pb=&b;

//定义指针变量printf("调用fun函数前:a=%d,b=%d\n",a,b);

fun(pa,pb);

//调用fun函数,指针变量作函数参数printf("调用fun函数后:a=%d,b=%d\n",a,b);}voidfun(int*p1,int*p2)

//指针变量作形参{

(*p1)++;

//使p1指向的变量值加1

(*p2)++;

//使p2指向的变量值加1

}思考:

实参指针和形参指针指向同一个内存单元,但它们本身是否占用相同的内存单元?5.2指向普通变量的指针

5.2.3指针变量作为函数参数【思考与总结】

函数调用时,传递的是变量的地址,使实参和形参指向同一个内存单元。当形参指向单元的值发生变化时,实参指向单元的值也随之变化。

若想通过函数调用得到n个要改变的值:可在主调函数中设n个变量,将这n个变量的地址传递给被调函数的形参(指针变量)。

实际上,数组名作为函数参数,其本质也如此。5.2指向普通变量的指针

5.2.3指针变量作为函数参数【例5.4】对输入的两个整数进行交换并输出。#include<stdio.h>voidswap(int*p1,int*p2);

//函数声明intmain(void){ inta,b;printf("请输入两个整数(用空格间隔):");scanf("%d%d",&a,&b); printf("调用swap函数前:a=%d,b=%d\n",a,b);

swap(&a,&b);

//调用swap函数,变量的地址作实参printf("调用swap函数后:a=%d,b=%d\n",a,b);}voidswap(int*p1,int*p2)

//指针变量作形参{ inttemp;

temp=*p1;*p1=*p2;*p2=temp;

}5.3指向数组的指针

5.3.1指向数组元素的指针

p=&a[0];//使p指向a[0]元素

指针变量既然可以指向变量,当然也可以指向数组元素(把某一元素的地址放到一个指针变量中)。

inta[10];//定义a为包含10个整型数据的数组

int*p;//定义p为指向整型数据的指针变量

下面两个语句等价:

int*p=&a[0]; int*p=a;

p、a、&a[0]均代表数组a的首地址(a[0]的地址)。5.3指向数组的指针

5.3.2通过指针引用数组元素

如果指针变量p已指向数组中的一个元素,则p+1指向同一数组中的下一个元素,p-1指向同一数组中的上一个元素。

(1)p+i和a+i就是a[i]的地址,即&a[i]。或者说它们指向数组a的第i个元素。

(2)*(p+i)或*(a+i)就是p+i或a+i所指向的数组元素,即a[i]。例如,*(p+5)或*(a+5)就是a[5]。即*(p+5)、*(a+5)、a[5]三者等价。(3)指向数组的指针变量也可以带下标,如p[i]与*(p+i)等价。

实际上,在编译时,对数组元素a[i]就是按*(a+i)处理的,因此[]实际上是变址运算符。

如果p的初值为&a[0],则:

5.3指向数组的指针

5.3.2通过指针引用数组元素【例5.5】输出数组中的全部元素。

引用一个数组元素有两种方法:下标法:a[i]。指针法:*(a+i)或*(p+i)

顺序访问数组元素时:第(3)种方法比第(1)、(2)种方法快,用指针变量直接指向元素,不必每次都重新计算地址。这种有规律地改变地址值(p++)能大大提高执行效率。(1)下标法#include<stdio.h>intmain(void){ inta[5]={1,3,5,7,9},i;

for(i=0;i<5;i++)printf("%d",

a[i]);printf("\n");}(2)通过数组名计算元素的

地址,找出元素的值#include<stdio.h>intmain(void){ inta[5]={1,3,5,7,9},i;

for(i=0;i<5;i++)printf("%d",*(a+i));printf("\n");}(3)用指针变量

指向数组元素

#include<stdio.h>intmain(void){inta[5]={1,3,5,7,9},i,*p;

for(p=a;p<a+5;p++)printf("%d",*p);

printf("\n");}for(p=a,i=0;i<5;i++,p++)5.3指向数组的指针

5.3.2通过指针引用数组元素

(1)可以通过改变指针变量的值(如p++)而指向不同的元素。而a++是错误的,因为a是数组名(数组的首地址),是常量。(2)要注意指针变量的当前值。

在使用指针变量指向数组元素时,要特别注意:

从运行结果看,没有实现要求。如何改正?#include<stdio.h>intmain(void){ inti,

a[5];

int*p=a;printf("请输入5个整数:");for(i=0;i<5;i++)scanf("%d",p++);for(i=0;i<5;i++,

p++)printf("%d",

*p);printf("\n");}【例5.6】通过指针变量输出a数组的5个元素。for(p=a,i=0;i<5;i++,p++)for(p=a;

p<a+5;p++)5.3指向数组的指针

5.3.2通过指针引用数组元素【例5.7】通过指针变量找出数组元素的最大值和最小值。#include<stdio.h>intmain(void){ inta[5]={23,

12,

34,

78,

55};

int*p,*max,*min;

//定义3个指针变量

p=max=min=a;

//将3个指针变量同时指向数组首元素for(p=a;p<a+5;p++){

if(*p>*max)max=p;

//更新max指向

if(*p<*min)min=p;

//更新min指向}printf("max=%d,min=%d\n",

*max,

*min);}5.3指向数组的指针

5.3.3用数组名作函数参数在4.4.2节曾介绍过数组名可以作函数的实参和形参。

实际上,C语言编译系统都是将形参数组名作为指针变量(存放地址)来处理的,并非真正开辟一个新的数组空间。voidf(intb[

],intn)相当于:void

f(int*b,intn)5.3指向数组的指针

普通变量、数组元素,普通变量的地址、指针变量、数组名都可以作为函数参数:5.3.3用数组名作函数参数5.3指向数组的指针

5.3.3用数组名作函数参数若有一实参数组,要想通过函数调用改变此数组中元素的值,有4种形式:(1)实参和形参都用数组名(2)实参用数组名,形参用指针变量5.3指向数组的指针

5.3.3用数组名作函数参数(3)实参和形参都用指针变量

(4)实参用指针变量,形参用数组名

若有一实参数组,要想通过函数调用改变此数组中元素的值,有4种形式:5.3指向数组的指针

【例5.8】用指针变量作函数形参,改写例4.8给出的程序。5.3.3用数组名作函数参数理解和练习:【例5.9】用指针变量作为函数的参数,改写例4.10给出的排序程序。#include<stdio.h>voidchange(intb[],intn);

//函数声明intmain(void){ inta[5]={1,

3,

5,

7,

9},i;printf("函数调用前:");for(i=0;i<5;i++)printf("a[%d]=%d",

i,

a[i]);printf("\n");

change(a,5);//调用change函数,实参:数组名a、数值5printf("函数调用后:");for(i=0;i<5;i++)printf("a[%d]=%d",i,

a[i]);printf("\n");}voidchange(intb[],

intn)

//形参:数组名

b、变量n{ inti;for(i=0;

i<n;i++)

b[i]++;}*bvoidchange(int

*b,intn)

//形参:指针变量b、变量n{ int*p;for(p=b;p<b+n;p++)

(*p)++;}5.3指向数组的指针

1、二维数组元素的地址C语言中,二维数组a又可看作是一个特殊的一维数组。有3个行元素:a[0]、a[1]、a[2],而每个行元素又是一个包含4个列元素的一维数组,此时把a[0]、a[1]、a[2]看作一维数组名。

根据一维数组的指针知识,a+i代表元素a[i]的地址&a[i],而在二维数组中,元素a[i]是包含4个元素的一维数组,因此a+i代表第i行的首地址(起始地址)。aa+1a+2a[0]、a[1]、a[2]既然是一维数组名,而数组名代表数组首元素的地址,因此a[0]代表一维数组a[0]中第0列元素的地址,即&a[0][0]。同理,a[1]代表&a[1][0],a[2]代表&a[2][0]。据此,a[i][j]的地址&a[i][j]可用a[i]+j表示。a[0]+0a[0]+1a[0]+2a[0]+35.3.4通过指针引用多维数组5.3指向数组的指针

a[i]与*(a+i)等价!1、二维数组元素的地址5.3.4通过指针引用多维数组

(1)a与a[0]指向同一个地址,区别:a指向一维数组,而a[0]指向a[0][0]元素。a+1中的“1”代表一行中全部整型元素所占的字节数(VC中为16字节),而a[0]+1中的“1”代表一个整型元素所占的字节数(VC中为4字节)。

(2)在行指针(a+i)的前面加一个*,就转换为列指针(指向第i行第0列元素)。例如,而*a、*(a+1)分别指向数组第0行第0列的元素、第1行第0列的元素。

在列指针a[i]前面加&,就成为指向第i行的行指针。例如,&a[0]是指向第0行的行指针。5.3指向数组的指针

2、指向二维数组的指针变量(1)指向二维数组元素的指针变量5.3.4通过指针引用多维数组【例5.10】用指向数组元素的指针变量输出3×4二维数组各元素的值。

分析:二维数组的元素在内存中是按行顺序存放的,12个元素的地址依次为a[0]~a[0]+11,因此可以用一个指向二维数组元素的指针,依次指向各个元素。#include<stdio.h>intmain(void){ inta[3][4]={{2,4,6,8},{10,12,14,16},{18,20,22,24}};

int*p=a[0];

//将a[0][0]元素的地址赋给指针变量p

for(;

p<a[0]+12;

p++){ if((p-a[0])%4==0) printf("\n");//每输出4个值换行printf("%4d",

*p); }printf("\n");}5.3指向数组的指针

(2)指向由n个元素组成的一维数组的指针变量:(*p)[n]

指针变量p先指向第0行a[0](即p=&a[0]),则p+1指向第1行a[1],p的增值以一维数组中n个元素的长度为单位。5.3.4通过指针引用多维数组2、指向二维数组的指针变量

p是指向由4个元素组成的一维数组的指针,p的值是该一维数组的起始地址。p不能指向一维数组中的某一个元素。5.3指向数组的指针

(2)指向由n个元素组成的一维数组的指针变量:(*p)[n]5.3.4通过指针引用多维数组2、指向二维数组的指针变量【例5.11】用指向由n个元素组成的一维数组的指针变量输出3×4二维数组各元素值。#include<stdio.h>intmain(void){ inta[3][4]={{2,4,6,8},{10,12,14,16},{18,20,22,24}};intj;int(*p)[4];//定义指向由4个元素组成的一维数组的指针变量p

for(p=a;p<a+3;

p++){for(j=0;j<4;j++)printf("%4d",

*(*p+j)); printf("\n"); }}5.3指向数组的指针

3、用指向二维数组的指针变量作函数参数5.3.4通过指针引用多维数组

用指针变量作形参,以接收实参数组名传递来的地址时,可有两种方法:(1)用指向二维数组元素的指针变量(列指针);(2)用指向由n个元素组成的一维数组的指针变量(行指针)。【例5.12】某测控系统,在上午、下午和夜间3个时间段内各检测4次温度,利用指向二维数组的指针,计算室内一天内的平均温度,并输出夜间检测到的4次温度值。intmain(void){ floatt[3][4]={{18,20,22,25},{26,24,21,19},{16,14,12,15}}//上午、下午、夜间温度

average(*t,

12);//计算平均温度,实参:指向t[0][0]元素的指针变量(列指针)

print(t,2);

//输出夜间温度值,实参:二维数组名t(首行指针)}voidaverage(float*p,intn)//求平均温度,形参:指针变量p、变量n{ floatsum=0,

aver;float*q;for(q=p;q<p+n;q++)sum=sum+(*q);aver=sum/n;printf("一天内的平均温度:%5.1f\n",

aver);}voidprint(float

(*p)[4],intn)//形参p是指向具有4个元素的一维数组的指针{ intj;printf("夜间内温度检测值:");for(j=0;j<4;j++)printf("%5.1f",

*(*(p+n)+j));printf("\n");}5.4指向字符串的指针

字符串广泛应用于嵌入式系统与物联网软件设计中,本节主要介绍字符串的引用方式和字符串在函数间的传递方式。5.4.1字符串的引用方式1、字符数组法【例5.13】用字符数组存放一个字符串,然后输出该字符串和第4个字符。#include<stdio.h>intmain(void){ charstr[]="IloveChina!";//定义字符数组strprintf("%s\n",

str);

//用%s格式输出str整个字符串printf("%c\n",

str[3]);

//用%c格式输出一个字符数组元素}5.4指向字符串的指针

2、字符指针法5.4.1字符串的引用方式【例5.14】用字符指针变量输出一个字符串和该串的第4个字符。

在C语言中,用字符数组用来存放字符串常量。因此可将字符串首元素(第1个字符)的地址赋给一个指针变量,通过指针变量来访问字符串,该指针就是指向字符串的指针。

使用%s输出时,先输出指针变量p所指向的一个字符,然后自动使p加1,使之指向下一个字符,再输出一个字符,…,直到遇到字符串结束标志'\0'为止。#include<stdio.h>intmain(void){

char*p="IloveChina!";

//定义字符指针变量p,并使其指向字符串的第1个字符printf("%s\n",

p);

//输出整个字符串printf("%c\n",

*(p+3));

//输出第4个字符}5.4指向字符串的指针

2、字符指针法5.4.1字符串的引用方式【例5.15】输出字符串中n个字符后的所有字符。#include<stdio.h>intmain(void){ intn=10;

char*ps="thisisabook";

//定义字符型指针变量,并使其指向字符串的第1个字符

ps=ps+n;printf("%s\n",

ps);}5.4指向字符串的指针

5.4.2字符串在函数间的传递方式【例5.16】自编字符串复制的函数。

在字符串处理运算中,可用字符数组名或字符指针变量作函数参数,传递字符串的起始地址,在被调函数中字符串的内容发生变化后,主调函数就可以引用改变后的字符串。5.4指向字符串的指针

5.4.3使用字符数组与字符指针变量的区别

用字符数组和字符指针变量都可实现对字符串的存储和运算。区别:1、存储内容不同

字符数组可存放整个字符串;而字符指针变量只能存放字符串某个字符的地址。2、赋值方式不同(1)对字符数组赋初值:

charst[]="CLanguage";(2)对字符指针变量赋初值:

char*ps="CLanguage";也可以写成:

char*ps; ps="CLanguage";而不能写成:

charst[20];st="CLanguage";

可见,使用指针变量处理字符串更加方便。但要注意:在使用指针变量时,需要对指针变量赋予确定的地址。【例5.17】用带下标的字符指针变量引用字符串中的字符。5.4指向字符串的指针

说明:可以用下标方式引用指针变量所指向的字符串中的字符。5.4.3使用字符数组与字符指针变量的区别#include<stdio.h>intmain(void){inti;

char*p="IloveChina!";//定义字符指针变量p,并使其指向字符串的第1个字符for(i=0;p[i]!='\0';i++)printf("%c",

p[i]);

//通过下标方式引用字符串中的字符printf("\n");}5.5指向函数的指针

(2)通过指针变量调用函数#include<stdio.h>intadd(intx,inty);

//函数声明intmain(void){inta,b,sum;

int(*p)(int,

int);

//定义指向函数的指针变量

p=add;

//使指针变量p指向add函数printf("请输入a、b的值:");scanf("%d%d",&a,&b);sum=(*p)(a,b);//通过指针变量调用add函数printf("a=%d,b=%d\n",a,b);printf("sum=%d\n",sum);}intadd(intx,inty){ return(x+y);}

编译系统为函数代码分配一段存储空间,其起始地址称为该函数的入口地址。【例5.18】用函数求整数a、b的和。利用指针变量调用函数的步骤和方法:

(1)定义指向函数的指针变量

类型标识符(*指针变量名)(函数参数列表);

(2)将函数的入口地址(函数名)赋给指针变量,使指针变量指向函数(3)通过“(*指针变量名)(函数参数列表)”调用函数C规定,函数名代表函数的入口地址,可定义一个指针变量存放函数的入口地址,则该指针称为指向函数的指针,简称函数指针。(1)通过函数名调用函数#include<stdio.h>intadd(intx,inty);

//函数声明intmain(void){ inta,b,sum;printf("请输入a、b的值:");scanf("%d%d",&a,&b);sum=add(a,b);//通过函数名调用add函数 printf("a=%d,b=%d\n",a,b);printf("sum=%d\n",sum);}intadd(intx,inty){return(x+y);}5.5指向函数的指针

练习:

教材【思考与实验】用起来更复杂,又有何用?

1、用函数名调用函数,只能调用所指定的一个函数;而通过指针变量可以根据不同情况先后调用不同的函数,使用灵活。【例5.19】输入两个整数,然后让用户选择1或2,选择1时调用max函数,输出两数中的大数;选择2时调用min函数,输出两数中的小数。2、指向函数的指针变量可作为函数参数进行信息传递。5.6返回指针值的函数(指针型函数)

一个函数可以返回指针型的值,即返回一个地址。声明返回指针值的函数(指针型函数),一般形式:

类型标识符*函数名(形参列表);

()优先级高于*,因此f先与()结合,表示这是f函数。调用该函数之后能得到一个int*型的指针(指向整型数据),即整型数据的地址。

例如:int*f(intx,inty);说明:

在后续的内存动态分配、链表及其操作、文件读写操作等内容将涉及指针型函数的应用方法。下面通过几个简单实例理解指针型函数的基本概念。

5.6返回指针值的函数(指针型函数)

【例5.20】利用指针型函数输出静态局部数组的元素值。

静态局部数组的内容在函数调用结束后仍被保留,因此在主函数中可通过指针变量p输出数组中元素的值。

若将数组a定义为动态局部数组,结果又如何?

#include<stdio.h>int*fun();

//指针型函数声明intmain(void){ inti;int*p;

//定义指针变量

p=fun();

//调用fun函数,获取一指向整型数据的地址for(i=0;i<5;i++,

p++)printf("%4d",

*p);printf("\n");}int*fun()

//指针型函数,返回指向整型数据的指针变量{

staticinta[]={1,2,3,4,5};//定义静态局部数组int*q=a;

//定义指针变量q,并指向数组a

return(q);

//返回数组a的首地址

}5.6返回指针值的函数(指针型函数)

【例5.21】利用指针型函数输出字符串(位于常量区)。若将此行代码改为:charstr[]=''abcde'';结果又如何?#include<stdio.h>char*fun();

//函数声明intmain(void){ char*ps;

//定义指针变量

ps=fun();

//调用fun函数,获取一指向字符型数据的地址printf("%s\n",ps);}char*fun()

//指针型函数,返回指向字符型数据的指针变量{

char*str="abcde";//定义指针变量,并指向字符串return(str);

//返回字符串的起始地址

}5.7指针数组、指向指针的指针

5.7.1指针数组1、指针数组的概念

指针数组用来存放一批地址,每一个元素都存放一个地址。

定义一维指针数组的一般形式:

类型标识符*数组名[数组长度];例如:int*p[3];

[]比*优先级高,p先与[3]结合,构成p[3]数组的形式,然后再与*结合,表示数组p的3个元素均为指向int型数据的指针变量。5.7指针数组、指向指针的指针

5.7.1指针数组1、指针数组的概念

【例5.23】利用指针数组指向多个整型变量,并输出各整型变量的值。

#include<stdio.h>intmain(void){ inta=10,b=20,c=30,i;

int*p[3]={&a,

&b,

&c};

//定义指针数组并使3个元素分别指向3个整型变量for(i=0;i<3;i++)printf("%d\n",

*p[i]);

//利用指针数组引用整型变量

}5.7指针数组、指向指针的指针

5.7.1指针数组1、指针数组的概念

【例5.24】利用指针数组指向一维整型数组的各元素,并引用一维整型数组的各元素。#include<stdio.h>intmain(void){ inta[3]={10,20,30},i;

int*p[3]={&a[0],&a[1],&a[2]};

//定义指针数组,并初始化for(i=0;i<3;i++)printf("%d\n",

*p[i]);

//利用指针数组引用整型数组元素}5.7指针数组、指向指针的指针

(1)多个字符串的处理方法一个字符串可用一维数组来存放,而多个字符串可用二维数组存放。

若用字符型指针引用多个字符串,则需要多个指针,因此也可利用字符型指针数组处理多个字符串。【例5.25】分别用二维数组和字符型指针数组处理多个字符串。2、指针数组的实际应用5.7.1指针数组#include<stdio.h>intmain(void){

charstr[3][5]={"ab","abc","abcd"};inti;for(i=0;i<3;i++)printf("%s\n",str[i]);}#include<stdio.h>intmain(void){

char*ps[3]={"ab","abc","abcd"};inti;for(i=0;i<3;i++)printf("%s\n",ps[i]);}5.7指针数组、指向指针的指针

(2)利用函数型指针数组实现对若干个函数的调用【例5.26】函数型指针数组的应用:实现对若干个函数的调用。2、指针数组的实际应用5.7.1指针数组#include<stdio.h>voidmax(intx,inty);

//函数声明voidmin(intx,inty);

//函数声明voidadd(intx,inty);

//函数声明intmain(void){ inta,b,i;

void(*p[3])(int,int)={max,min,add};

//定义函数型指针数组,存放3个函数名printf("请输入两个整数:");scanf("%d%d",&a,&b);printf("a=%d,b=%d\n",a,b);for(i=0;i<3;i++)

(*p[i])(a,b);

//利用函数型指针数组调用函数}5.7指针数组、指向指针的指针

(3)指针数组作main函数的形参

在一些人机交互应用系统中,main函数是可以带参数的。例如:

intmain(intargc,char*argv[])2、指针数组的实际应用5.7.1指针数组

操作系统调用main函数时,将实参传递给main函数。在操作系统命令状态下,命令行的一般形式:命令字(可执行文件名)参数1参数2

……

参数n

例如:可执行文件名为SW.exe,现将两个字符串“OPEN”、“CLOSE”作为参数传递给main函数,则命令行可写成:SWOPENCLOSE

说明:argc的值和argv[]各元素的值都是系统自动赋值的。其中,argc的值等于命令行中字符串的总个数(包括命令字);argv指针数组中的各个元素依次指向命令行中的各个字符串。

5.7指针数组、指向指针的指针

【例5.27】测试带有参数的main函数。

在VC++2010开发环境中建立项目,项目名为test,保存路径为E:\test。在此项目中,建立ex.c文件:(3)指针数组作main函数的形参2、指针数组的实际应用5.7.1指针数组#include<stdio.h>intmain(intargc,char*argv[]){ while(argc>0){ printf("%s\n",

*argv);

//输出命令行中的字符串

argv++;argc--;}}5.7指针数组、指向指针的指针

5.7.2指向指针的指针

inta=3; int*num=&a;//定义指针变量num,指向变量a printf("%d\n",*num);//通过指针变量num引用变量a

通过指针变量num间接访问变量a:“单级间址”访问方式。

若再定义一个指针变量p,存放指针变量num的地址,则可通过指针变量p访问变量a:“二级间址”访问方式。p是指向指针数据的指针变量,简称“指向指针的指针”。

定义指向指针的指针变量的一般形式:类型标识符**指针变量名;例如:int**p;//指针变量p指向一个整型的指针变量5.7指针数组、指向指针的指针

【例5.28】分析程序,理解指向指针的指针。5.7.2指向指针的指针#include<stdio.h>intmain(void){ inta=3;

int*num=&a;

int**p=#printf("%x\n",

num);printf("%x\n",

*p);printf("%d\n",

**p);}5.7指针数组、指向指针的指针

在实际应用中,指向指针的指针常与指针数组配合使用处理问题。【例5.29】有一指针数组num,其元素分别指向一维整型数组a的各元素。现用指向指针的指针变量p,依次输出整型数组a中各元素的值。5.7.2指向指针的指针#include<stdio.h>intmain(void){ inta[3]={10,20,30},i;

int*num[3]={&a[0],&a[1],&a[2]};

//定义指针数组num

int**p=num;

//定义指向指针的指针变量p,并指向指针数组num的首元素for(i=0;i<3;i++,

p++)

printf("%d\n",**p);//利用指向指针的指针变量p引用整型数组元素}5.7指针数组、指向指针的指针

5.7.2指向指针的指针【例5.30】有一指针数组ps,其元素分别指向3个字符串。现用指向指针的指针变量p,依次输出3个字符串。在实际应用中,指向指针的指针常与指针数组配合使用处理问题。#include<stdio.h>intmain(void){ inti;

char*ps[3]={"ab","abc","abcd"};

//定义指针数组ps

char**p=ps;

//定义指向指针的指针变量p,并指向指针数组ps的首元素for(i=0;i<3;i++,p++)printf("%s\n",*p);

//利用指向指针的指针变量p输出字符串}5.8内存动态分配与指向动态内存区的指针变量

5.8.1内存动态分配的概念

在4.5节中介绍过全局变量和局部变量,全局变量分配在内存中的静态存储区,非静态的局部变量(包括形参)分配在内存中的动态存储区。

除此之外,C语言还允许建立内存动态分配区域,用来存放一些临时用的数据,这些数据不必在程序中的声明部分定义,也不必等函数结束时才释放,而是需要时随时申请开辟,不需要时随时释放。在内存中动态分配的数据,只能通过指针来引用。5.8.2内存动态分配的方法5.8内存动态分配与指向动态内存区的指针变量

对内存的动态分配是通过库函数来实现的,对应的头文件是stdlib.h。1、malloc函数:void*malloc(unsignedsize);

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论