第六章指针Word格式.docx

上传人:b****7 文档编号:22854697 上传时间:2023-02-05 格式:DOCX 页数:17 大小:32.68KB
下载 相关 举报
第六章指针Word格式.docx_第1页
第1页 / 共17页
第六章指针Word格式.docx_第2页
第2页 / 共17页
第六章指针Word格式.docx_第3页
第3页 / 共17页
第六章指针Word格式.docx_第4页
第4页 / 共17页
第六章指针Word格式.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

第六章指针Word格式.docx

《第六章指针Word格式.docx》由会员分享,可在线阅读,更多相关《第六章指针Word格式.docx(17页珍藏版)》请在冰豆网上搜索。

第六章指针Word格式.docx

 

函数max()入口地址

通常我们关心的不是具体的地址值,而是每个实体的“起始地址”。

实体地址表示法1:

·

普通变量——&

a,&

b,&

数组d[3]——d(数组名)&

d[0],&

d[1],&

对二维数组,可用单下标法表示每行首地址。

如对charx[3][4],可用x[0]、x[1]、x[2]分别表示每一、二、三行的首地址。

函数max()——max(函数名)入口地址

取地址运算符(适用于普通变量或数组元素)

实体地址表示法2:

指针

适合于地址运算(加减等)

【说明】字符串是一种特殊的实体,存放在内存用户区的常量区(参见第四章第五节)。

2.指针(pointer)

实体地址的一种表示法(便于编程处理)。

指针是一种特殊的数据类型——存放的是某个实体的地址值。

为什么要用指针?

直接访问:

通过变量(实体)名→定义时分配的地址→变量值访问变量

好比“先坐再买票”看电影,来一个观众,分配一个空位给他去坐,并且还要在纸上记一个某人坐在哪里。

这种方式对用户来说很方便(“直接就座”),但对系统来说,“找某人”就极不方便(间接:

查名字→座号)

间接访问:

通过“指针”访问变量

好比先买票(票上座号——指针),再按号入座看电影。

这种方式对用户来说属于“间接就座”,便对系统查找来说就很直接,且便于处理。

尤其对于数组(团体),可通过指针简单自加或自减,对整个数组进行处理。

【变量的“指针”】变量的地址

3.指针变量P159

存放“指针”(地址值)的特殊变量。

定义方法:

类型标识符*变量名

如int*a;

char*b;

float*c;

此处,指针变量a,b,c分别指向某个未确定的整型变量、字符变量和实型变量。

但指针变量a,b,c本身是整数(地址)。

(编程测试可以发现在PC机上指针变量取值范围为-32767~32767,超出该范围编译就会出错,以此推算PC机地址长度为16位即2个字节)。

以下程序亦可证实这一点:

main()

{char*a;

longint*b;

double*c;

printf("

%d,%d,%d\n"

sizeof(a),sizeof(b),sizeof(c));

}

结果:

2,2,2

【注意】数组名是常量,不能自加、自减或重新赋值,指针变量则可以。

如chara[10],*b,x=5;

a++;

或a=100;

a=x;

×

(编译出错)

b++;

或b=100;

b=x;

√(编译不出错)

4.指针变量的运算与引用P159

a.与指针有关的运算符

&

取地址运算符(变量名前加一个&

,表示该变量的地址)

*指针运算符(“间接访问”运算符)

*放在某个指针变量前,表示该指针变量所指向的变量。

(注意与乘号“*”的区别)

简单记忆:

如果p被定义成指向普通变量的指针变量,则*p代表该变量的值。

如int*p,a=5;

p=&

a;

则*p代表变量a的值(5)。

·

如果p被定义成指向某个数组的指针变量,则*p代表该数组中某个元素的值。

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

p=a;

则*p代表数组a中某个元素的值。

【例】main()

{int*p,a[12]={1,2,3,4,5};

clrscr();

for(;

*p<

5;

p++)

%d"

*p);

结果:

1234

如果p被定义成指向某个字符数组或某个字符串的指针变量,则*p代表某个字符。

如int*p,a[3]=”abcd”;

p代表a中的某个字符

【例】

{char*p,a[12]="

abcde"

;

*p;

%c"

}

abcde

{char*p;

p="

与*组合使用时:

若inta,*p;

p=&

则&

*p=&

a=p;

*&

a=a=*p

开头为地址,*形状为变量值,&

和*可以看作互相“抵消”。

【例一】main()

{inta=5,*p;

printf(“%d,%d,%d\n”,p,*p,a)

}

结果(按右图):

2000,5,5

【例二】以下程序的运行结果是什么?

{inta,b=10,*p;

b;

a=*p+3;

a=%d,b=%d\n"

a,b);

a=13,b=10

【例三】main()

{floatx,y;

int*p;

x=3.14;

x;

y=*p;

y=%f\n"

y);

y=-2621.000000(把int*p改为float*p后,结果正确y=3.140000)

b.指针变量的算术运算

只有加、减两种p+5p++p-1p--

注意加减运算是以实体为单位而不是以字节为单位。

此外,两个指针变量可以相减。

即:

如果两个指针变量指向同一数组时,两个指针变量值之差是两个指针之间的元素个数。

P213

但两个指针变量相加并无实际意义。

c.指针的逻辑比较P213

指针变量指向同一个对象(如数组)的不同单元地址时,才可以进行比较。

地址在前者为小。

实例:

《试题汇编》【9.56】(此处不讲解程序)

p=NULL表示指针变量为空值(不指向任何变量)。

任何指针变量或地址都可以与NULL作相等或不相等的比较。

如if(p==NULL)……

【注意】在指针p指向某个实体的地址之前,不可对*p进行赋值。

否则可能发生意想不到的错误(p随便指向某个单元)。

典型错误:

1、指针变量定义后,未指向具体存储单元就使用(此时指针变量所指单元是任意的)

2、指针变量定义后,虽指向具体存储单元但未赋值就参加运算(此时其值是任意的)

【例一】分析以下句子的错误

int*p,*q;

q=p;

p指向?

(错误类型1)

inta=20,*p,*q=&

*p=*q;

inta,*p,*q;

q=&

*q=?

(错误类型2)

【例二】若有定义char*p,ch;

则不能正确赋值的语句组是。

(01-1-06考题)

A)p=&

chB)p=(char*)malloc

(1);

Scanf(“%c”,p);

*p=getchar();

C)*p=getchar();

D)p=&

ch;

P=&

*p=getchar();

答案:

C(指针p未指向任何变量就赋值)

【例三】如果有定义语句char*a,b[30];

试判断以下各句哪些是正确的?

A)a=”abcde”;

B)b=”abcde”;

C)scanf(“%s”,a);

×

D)scanf(“%s”,b);

【例四】若有说明:

int*p,m=5,n;

试判断以下各句哪些是正确的?

《试题汇编》【9.13】

A)p=&

n;

scanf(“%d”,&

p);

B)p=&

scanf(“%d”,*p);

C)scanf(“%d”,&

n);

*p=n;

D)p=&

*p=m;

D

【例五】若有说明:

int*p1,*p2,m=5,n;

A)p1=&

m;

p2=&

p1;

(p2应为**p2)

B)p1=&

p2=&

*p1=*p2;

(*p2=?

C)p1=&

*p2=*p1;

(p2指向?

D)p1=&

p2=p1;

5.多重指针

形式如int**p等效于int*(*p)

——定义一个二级指针(指向指针的指针)存放某个指针变量的地址

在引用时,*p是p间接指向的对象的地址。

**p是p间接指向的对象的值。

【例一】以下程序段的输出是什么?

int**pp,*p,a=20,b=30;

pp=&

p;

p=&

printf(“%d,%d\n”,*p,**pp);

30,30

6.指针变量作为函数参数

【例一】P163例9.3

#include<

stdio.h>

fun(int*i)

{staticinta=1;

*i+=a++;

{intk=0;

fun(&

k);

printf("

%d\n"

k);

第一次调用fun(&

k)后,k=*i=1,a=2;

第二次调用fun(&

k)后,k=*i=3,a=3;

3

【讨论】如果fun()函数中没有static,结果呢?

(2)

为了实现:

在被调函数中改变实体值,然后在主调函数中使用这些改变了的实体值

主要技术要点在于:

主调函数的实参和被调函数对应的形参都必须用地址表示——地址传递

用于作实参的地址可以是:

变量名&

数组元素名(很少使用)

数组名

指针变量名

对应的形参则为:

数组定义

指针定义

二、指针与数组

1.C语言的有关规定

对于数组inta[10];

C语言规定:

①可以用数组名a代表数组首地址(即数组第一个元素a[0]的地址)

即a=&

a[0]

【注意】数组名a是个常量,只能表示该数组的首地址,不可重新赋值。

②可以用指针变量p代表数组地址或数组元素的地址。

inta[10],*p;

p=a;

或p=&

a[0];

【注意】p是变量,并不固定表示首地址,p=a只是特例,可以重新赋值。

③可以用a+i或p+i表示数组元素a[i]的地址。

如:

a+5即&

a[5]

p+5即&

a[5]

本质上,a+i或p+i相当于a+i×

d或p+i×

d

d—每个数组元素占的字节数

【讨论】如果p=&

a[2],那么p+1和p+2指向何处?

④可以用*(p+i)或*(a+i)表示数组元素a[i]。

⑤可以用p[i]表示*(p+i)即a[i]。

注意事项:

①注意指针变量当前值P169例9.6

②注意不要超界

③常见表示法:

*p++等价于*(p++)先取*p值,然后p++。

*(++p)p先自加,然后取*p的值。

*p--与*(--p)功能同上。

2、数组、指针与函数调用

由上可知:

数组名a——常量,恒为数组第一元素地址(a=&

a[0])

指针变量p——变量,可为数组任一元素地址(p=&

a[i],仅当p=a时,p=&

a[0])。

所以,若在主调函数中有一数组,需通过被调函数改变其元素值,可有四种地址传送方式可用;

P175

主调函数中实参被调函数中形参

数组名a数组名b

指针变量p(p=a)指针变量x

数组名a指针变量x

指针变量p(p=a)数组名b

其本质都是将数组名a或指针变量p所代表的数组首地址,传给形参首地址b或x

3、二维数组问题

①排队表示法(一维方法)

以a或a[0]为“起点”,顺序排列,直到“终点”(成一队列,不考虑行列)。

a[0]a[0]+i

如果inta[N][M],*p;

或p=a[0];

则数组元素a[i][j]的存储地址为:

a[0][0]+i×

N+j或a[0]+i×

N+j

且有a[0]+11,p+11从a[0]开始第11号元素的地址

*(a[0]+11),*(p+11)从a[0]开始第11号元素的值

此时可用单循环遍历整个数组各个元素:

for(i=0;

i<

N*M;

i++,p++)或for(p=a[0];

p<

a[0]+N*M;

②行列表示法(二维方法)

以a=&

a[0][0]为“原点”(按行列分)。

此时数组元素a[i][j]的地址可以表示为:

a[i][j]

a[i]+j

*(a+i)+j

而数组元素a[i][j]的值可以表示为:

*(a[i]+j)

*(*(a+i)+j)

此时,欲遍历该数组的各个元素,必须用双重循环:

N;

i++)

for(j=0;

j<

M;

j++)

4、行指针

形式:

int(*p)[n]

含义:

p为指向含有n个元素的一维数组的指针变量。

P212

使用:

二维数组可以视为由若干一维数组组成。

若inta[4][5];

int(*p)[5];

p=a[0];

则(*p)[0]=a[0][0];

(*p)[1]=a[0][1];

(*p)[2]=a[0][2];

……

(*(p+1))[0]=a[1][0];

(*(p+1))[1]=a[1][1];

(*(p+i))[j]=a[i][j];

【例】若有以下定义和语句,且0≤i<4,0≤j<3,则不能访问a数组元素的是。

inti,(*p)[3],a[][3]={1,2,3,4,5,6,7,8,9,10,11,12};

A)*(*(a+i)+j)B)p[i][j]

C)(*(p+i))[j]D)p[j]+j

D(p[j]+j是个地址)2002-1-6考试第27题

5、指针与字符串

【例一】求以下程序的运行结果。

main(){

char*pc="

#Fujian##Province#"

while(*pc)

{while(*pc=='

#'

)pc++;

if(*pc=='

\0'

)break;

*pc);

pc++;

\n"

);

FujianProvince

【例二】把字符串t复制到字符串s中。

①数组方案

chars[15],t[]="

Iamastudent."

inti=0;

while((s[i]=t[i])!

='

i++;

%s\n%s"

s,t);

②指针方案

char*t="

*s="

"

char*t1=t,*s1=s;

while((*s=*t)!

{s++;

t++;

s1,t1);

Iamastudent.

Iamastudent.

【讨论】指针方案中为什么要使用char*t1=t,*s1=s;

语句?

(s++;

的结果是两指针都指向字符串的未尾’\0’处。

所以如果输入s和t将无字符输出)

∴使用指针时要注意当前指针的位置!

【例三】以下函数的功能对应于。

intfun(char*s,char*t)

{while(*s)&

(*t)&

(*t==*s)}/*在s和t均未结束且相比较的字符相同时继续循环*/

{t++;

/*将t下移一个字符*/

s++;

/*将s下移一个字符*/

return(*s-*t);

/*如果两个字符相同,返回值为0,否则不为0*/

A)strlen(s)+strlen(t)B)strcmp(s,t)

C)strcpy(s,t)D)strcat(s,t)

B

技巧:

用*s作循环条件,当循环到字符串结束处时自动结束循环)

while(*s)

{…;

s++};

6、指针数组

定义:

char*p[5];

功能:

定义数组p[5],其每个元素p[0]、p[1]、…p[4]都是指针变量。

通常用于指向一组字符串。

此时,对于p[i],其下标表示第i个字符串,p[i]本身是第i个字符串的首地址。

与行指针的区别:

行指针——只能指向二维数组的某一行(靠p+i来换行)。

其元素是某一行中对应字符。

指针数组——其元素分别向二维数组的首地址。

典型应用:

带参数的主函数P210

【例一】已知TEST.C的源程序如下:

(此部分内容可参见教材P210~211)

main(intargc,char*argv[])

{while(argc>

1)printf("

%s"

argv[--argc]);

将该文件编译后,在命令行输入:

testabc123则该程序运行结果是什么?

123abc

【分析】执行时,argc的值为3(从命令行输入testabc123共计三项)

argv[0]=”test”argv[1]=”abc”argv[2]=”123”

【例二】以下程序经过编译连接后得到的可执行文件名为echo.exe,在dos提示符下输入,则在屏幕上将显示Mycomputer。

argv[0]

echo

argv[1]

My

argv[2]

computer

argc=3

main(intargc,char*argv[])

{inti;

for(i=1;

argc;

%s%c"

argv[i],(i<

argc-1)?

'

'

:

\n'

A)MycomputerB)echoMycomputer

C)MycomputerD)main(Mycomputer)

【分析】执行时,argc的值为3(从命令行输入echoMycomputer共计三项)

argv[0]=”echo”argv[1]=”My”argv[2]=”computer”

三、指针与函数

1、指向函数的指针变量P196

可以用指针变量指向一个函数。

一个函数在编译时被分配给一个“入口地址”。

定义方法:

类型标识符(*指针变量名)();

如int(*p)();

指向一个返回整型值的函数

用法:

设有函数fun(a,b)

令p=fun;

则有(*p)(a,b)相当于fun(a,b);

此时c=(*p)(a,b)与c=fun(a,b)等效。

2、返回指针值的函数:

一般形式int*a(x,y);

表示该函数的返回值是一个指针。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 外语学习 > 其它语言学习

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1