第8章_指针

第8章_指针
第8章_指针

第8章指针 ............................................................................................................... - 1 -

一、指针概述............................................................................................................. - 1 -

二、指针与一维数组 ................................................................................................. - 3 -

三、指针与二维数组 ................................................................................................. - 5 -

四、指针与字符串 ..................................................................................................... - 9 -

五、指针与函数....................................................................................................... - 10 -

六、指针数组与多级指针 ....................................................................................... - 11 -

习题8....................................................................................................................... - 13 - 习题8答案............................................................................................................... - 15 - 补充题....................................................................................................................... - 18 - 补充题答案............................................................................................................... - 35 -

第8章指针

一、指针概述

1.指针的概念

在计算机中,对一个内存单元的访问(即存取数据)是通过地址来实现的,地址“指向”需要操作的内存单元。因此在C语言中,把地址形象地称为指针。如变量a的指针就是变量a的地址。

2.指针变量

(1)指针变量的定义

一般形式:

类型标识符 *变量名;

例如:

int *p1,*p2;

定义了2个指向int型数据的指针变量p1、p2,即它们只能存放int型变量的地址。

在定义指针变量时可以对其进行初始化,例如:

int a;

int *p=&a;

int a,*p=&a;

指针变量p中存放了变量a的地址。

(2)指针变量的引用

指针变量的使用与两个运算符“&”、“*”有密切关系。

&:取地址运算符,用于求变量在内存中的地址,运算符的操作对象必须是存储单元(如变量、数组元素等)。

*:指针运算符(或称间接访问运算符),间接访问指针变量指向的对象。指针运算符的操作对象必须是指针。

例如:

int a=6, *pa; /* 定义pa为指向int型数据的指针变量*/

pa=&a; /* 将a的地址赋给pa */

*pa=28; /* 将28赋给pa指向的变量a,*pa即为a */

(3)使用指针应注意的几种情况

1)在指针变量中只能存储地址

例如:

int a,*p,*q;

p=2000; /* 不正确*/

q=&a; /* 正确*/

2)初始化指针变量与用赋值语句给指针变量赋值在表示方法上的区别

语句“int a,*p=&a;”与“int a,*p; p=&a;”是等价的。

但“int a,*p; *p=&a;”中的赋值语句是错误的。

3.指针运算

指针也是一种数据类型,对于指针类型的数据,它只能做以下几种运算。

(1)指针之间的赋值运算

指针变量之间可以进行赋值运算,但必须是同一类型。例如:

int a,b,*pi=&a; /* 初始化pi为a的地址*/

float x,*p1,*p2=&x;

p1=p2; /* 正确*/

p1=pi; /* 错误,赋值运算符左右两边指针类型不同*/

(2)指针与整数的加、减运算

一个指针与一个整数进行加、减运算,其结果仍是一个指针。一般来说,当指针指向数组时,指针加、减整数操作才有意义。如果指针p是指向数组中的某个元素,加上整数n后,新指针p+n指向后续的第n个元素。例如:

int a[4]={1,2,3,4},*pa;

pa=a; /* 数组名a是地址常量,其值是数组的首地址,即&a[0] */

pa=pa+2; /* 执行赋值后,pa指向元素a[2] */

4.指针作为函数的参数

例8.1编写函数swap1,交换两个变量的值。

程序如下:

#include

void main()

{ float a, b;

void swap1(float *x, float *y); /* 函数声明,参数为指针类型*/

scanf("%f%f",&a,&b);

swap1(&a,&b); /* 把a、b的地址传给形参*/

printf("a=%.1f b=%.1f\n",a,b);

}

void swap1(float *x,float *y) /* 定义形参为指针变量*/

{ float t;

t=*x; *x=*y; *y=t; /* 交换指针x、y所指向的对象*/

}

程序运行情况:

3.4 5.6↙

a=5.6 b=3.4

二、指针与一维数组

1.一维数组元素的表示

对数组元素的引用除了用下标表示法外,也可以用指针表示法来实现。

(1)下标表示法和指针表示法

若定义一维数组为:int a[5]; 则要引用数组a的第i+1个元素(i从0开始编号),可以用下述两种方法:

●下标表示法:a[i]

●指针表示法:*(a+i)

这两种方法是等价的。

(2)用指针变量引用一维数组元素

将数组元素的地址存放在指针变量中,通过指针变量引用数组中的各元素。

例8.2用指针变量给一维数组元素赋值,并输出各元素的值及元素之和。

程序如下:

#include

void main()

{ int a[10],i,j,s;

int *p;

for(p=a;p

p=a; /* 使p重新指向第1个元素*/

for(s=0,i=0;i<10;i++) s+=*(p+i); /* *(p+i)表示a[i] */

for(i=0;i<10;i++) printf("%3d",p[i]); /* p[i]表示a[i] */

printf("\ns=%d",s);

}

程序运行情况:

1 2 3 4 5 6 7 8 9 10↙

1 2 3 4 5 6 7 8 9 10

s=55

2.数组名作为函数的参数

由于数组名是一个地址常量,因此用数组名作为函数的参数,实际上就是用指针作函数的参数。

例8.3编写函数,将数组中的n个整数从小到大排序。

程序如下:

#include

void main()

{ int t,b[10]={2,6,7,0,9,5,3,1,8,4};

int i,j,k;

void sort(int a[],int n); /* 函数声明*/

for(i=0;i<10;i++) printf("%3d",b[i]);

printf("\n");

sort(b,10); /* 数组名作参数,传递数组首地址*/

for(i=0;i<10;i++) printf("%3d",b[i]);

printf("\n");

}

void sort(int a[],int n) /* 定义排序函数,将数组a中n个元素排序*/ { int i,k,t,j;

for(i=0;i

{k=i;

for(j=i+1;j

if(a[k]>a[j]) k=j;

t=a[k];a[k]=a[i];a[i]=t;

}

}

运行结果如下:

2 6 7 0 9 5

3 1 8 4

0 1 2 3 4 5 6 7 8 9

三、指针与二维数组

1.二维数组中的指针

(1)元素指针

二维数组中每个元素的地址即为元素指针(或列指针)。

例如,对于元素a[i][j]的指针有如下三种表示方法:

1)&a[i][j]

2)a[i]+j

3)*(a+i)+j

二维数组中每个元素也有三种表示方法:

1)a[i][j]

2)*(a[i]+j)

3)*(*(a+i)+j)

(2)行指针

二维数组中每一行的首地址称为行指针。二维数组名是一个行指针。

例如,对于二维数组a的第i+1行的指针为:

a+i

行指针加1,则指向数组的下一行。

2.指向二维数组元素的指针变量

了解了二维数组的指针后,可以用指针变量指向二维数组及其元素。

(1)指向数组元素的指针变量

例8.4输入一个3×4的矩阵到二维数组中,输出该矩阵,并且输出它的最大值元素及行列号。

程序如下:

#include

void main()

{ int a[3][4], i,j,*maxp; /* maxp为指向元素的指针*/

for(i=0;i<3;i++) /* 输入矩阵*/

for(j=0;j<4;j++)

scanf("%d",*(a+i)+j); /* *(a+i)+j是a[i][j]的地址*/

for(i=0;i<3;i++) /* 输出矩阵*/

{ for(j=0;j<4;j++)

printf("%3d",*(*(a+i)+j)); /* *(*(a+i)+j)即a[i][j] */

printf("\n");

}

maxp=*a; /* 指针变量maxp指向元素a[0][0] */

for(i=0;i<3;i++)

for(j=0;j<4;j++)

if(*maxp<*(*(a+i)+j))

maxp=*(a+i)+j;

i=(maxp-*a)/4; /* 计算行号*/

j=maxp-*(a+i); /* 计算列号*/

printf("max=%d,i=%d,j=%d\n",*maxp,i+1,j+1);

}

运行情况:

1 2 3 4 5 6 7 8 9 10 12 11↙

1 2 3 4

5 6 7 8

9 10 12 11

max=12,i=3,j=3

(2)定义行指针变量

行指针变量也称为指向一维数组的指针变量,一般定义形式为:

类型标识符(*指针变量名)[常量表达式];

其中常量表达式表示一行含有多少个元素。在定义行指针变量时,必须确定每一行所含的元素个数。例如:

int (*p)[4], (*q)[6], a[3][4], b[2][6];

p=a; /* p指向a的第l行的地址*/

q=b; /* q指向b的第l行的地址*/

例8.5输入一个4×4的矩阵到二维数组中,分别计算出二维数组中指定行,指定列的元素之和。

程序如下:

#include

void main()

{ int a[4][4],(*p)[4], s1,s2,i,j,n,m; /* p为行指针变量*/

for(i=0;i<4;i++) /* 输入4×4矩阵*/

for(j=0;j<4;j++)

scanf("%d",*(a+i)+j); /* *(a+i)+j是元素a[i][j]的地址*/ scanf("%d%d",&n,&m); /* 输入指定的行、列*/

p=a+n-1; /* p指向第n行*/

for(s1=0,j=0;j<4;j++) /* 计算第n行元素之和*/

s1+=*(*p+j); /* *(*p+j) 即元素a[n-1][j] */ p=a; /* p指向第1行*/

for(s2=0,i=0;i<4;i++) /* 计算第m列元素之和*/

s2+=*(*(p+i)+m-1); /* *(*(p+i)+m-1)即元素a[i][m-1] */ printf("%d %d",s1,s2);

}

运行结果如下:

1 2 3 4↙

2 3 4 5↙

4 5 6 7↙

5 6 7 8↙

1 1↙

10 12

3.二维数组的行指针作函数参数

(1)行指针变量作函数形参

例8.6编写函数,将4×4矩阵的右上三角元素都设置成0(包括对角线上的元素),其余元素不变。

程序如下:

#include

void change(int (*x)[4],int n,int m) /* 行指针变量x作函数形参*/

{ int i,j;

for(i=0;i

for(j=0;j

if(i<=j) *(*(x+i)+j)=0; /* *(*(x+i)+j)即x[i][j] */

}

void main()

{ int a[4][4],i,j;

printf("\n");

for(i=0;i<4;i++)

{ for(j=0;j<4;j++)

{ a[i][j]=1+i+j; /* 输入矩阵 */

printf("%3d",a[i][j]); /* 输出矩阵 */

}

printf("\n");

}

change(a,4,4); /* 调用函数 */

printf("\n");

for(i=0;i<4;i++) /* 输出修改后的矩阵 */

{ for(j=0;j<4;j++)

printf("%3d",a[i][j]);

printf("\n");

}

}

程序运行结果:

1 2 3 4

2 3 4 5

3 4 5 6

4 5 6 7

0 0 0 0

2 0 0 0

3 4 0 0

4 5 6 0

(2)二维数组名作函数形参

由于二维数组名就是一个行指针,所以在定义函数时可以用二维数组名作形参。

用二维数组名作形参的一般格式为:

类型标识符数组名[ ][长度],int n, int m

二维数组名作形参时,必须指定第二维的长度,且长度必须与对应的实参数组的第二维长度一致。形参n、m用来指定函数中对二维数组处理时的行数和列数。

下面将例8.6的程序中的函数改写如下:

void change(int x[][4],int n,int m) /* 定义函数 */

{ int i,j;

for(i=0;i

for(j=0;j

if(i<=j) x[i][j]=0; /* 将矩阵右上三角元素置0 */

}

程序的main函数不变,则运行结果相同。

四、指针与字符串

1.字符串的表示形式

(1)字符串指针

字符串的首地址(即第一个字符的地址)即为字符串指针。对于一个字符串常量其值就是一个字符串指针,表示该字符串在内存中第一个字符的地址。若字符数组中存放一个字符串,其数组名就是字符串指针,指向字符串的首字符。

(2)用字符数组存放字符串

例如

char a[ ]=”Beijing China”;

数组名a就代表字符串的首地址(即首字符’B’的地址)。

(3)用字符指针变量指向字符串

用字符指针变量指向字符串的方法有两种形式,如

char *p=”a string”; /* 定义时初始化*/

或char *p; p=”a string”; /* 定义之后,再赋值*/

变量p指向字符串”a string”在内存中的地址。

(4)字符串的引用

字符串一般放在字符数组中或用指针变量指向一个字符串,引用时通过字符数组名或指向字符串的指针变量来引用字符串。

例8.7用字符数组名或字符指针变量引用字符串。

程序如下:

#include

void main()

{ char a[]="Hello,Everyone";

char *p=a; /* p,a指向同一字符串*/

printf("%s\n%s\n",a,p);

}

运行结果:

Hello,Everyone

Hello,Everyone

2.字符串指针作函数参数

将一个字符串从一个函数传递到另一个函数,可以用地址传递的办法,即用字符数组名作参数或用指向字符的指针变量作参数。在被调函数中可以改变字符串的内容,在主调函数中可以得到改变了的字符串。

例8.8编写函数计算字符串的长度。

#include

int length(char *s)

{ int k=0;

while(*s!='\0'){ k++; s++;} /* k表示字符个数*/

return k;

}

void main()

{ char a[80]={"Beijing\nChina"};

printf("length: %d\n",length(a));

}

运行结果:

length: 13

五、指针与函数

1.指向函数的指针

定义指向函数的指针变量的一般形式:

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

其中类型标识符表示指针变量所指向的函数的返回值类型,函数形参类型表示指针变量所指向的函数所具有的参数类型。例如:

double (*fun)(double);

fun=sqrt; /* 使fun指向函数sqrt */

可以用指针变量fun调用函数sqrt。如fun(5)或(*fun)(5))与sqrt(5)的作用一样。

2.返回指针的函数

一个函数不仅可以返回整型、实型、字符型等数据,也可以返回指针类型的数据,即地址值。

定义返回指针的函数的一般形式:

类型标识符 *函数名(类型标识符形参, 类型标识符形参,… )

其中“*”表示函数返回的值是指针。例如:

int *fun(float x, float y)

fun是函数名,调用它后能得到一个指向int型数据的指针(地址)。

例8.9编写函数,返回给定的字符在字符串中第一次出现的该字符的指针。

#include

char *find(char *p, char c) /* 查找c中的字符在p所指字符串中的地址*/ { char *pc;

pc=p; /* 将字符串首地址赋给指针变量pc */

while(*pc!='\0')

{ if(*pc!=c) pc++;

else return pc; /* 返回找到的字符地址*/

}

return NULL; /* 没找到,返回空指针*/

}

void main()

{ char s[80],c,*p;

printf("Enter a string:\n");

gets(s); /* 输入一个字符串*/

printf("Enter a character:\n");

scanf("%c",&c); /* 输入要查找的字符*/

p=find(s,c); /* 调用函数,将返回的指针赋给p */

if(p==NULL) printf("no find\n");

else

{ printf("the address of %c is: %x\n",c,p);

printf("is the %dth character\n",p-s+1);

}

}

运行情况:

Enter a string:

chin a↙

Enter a character:

n↙

the address of n is: f8e

is the 4th character

六、指针数组与多级指针

1.指针数组

一个数组,其元素均为指针类型,则称为指针数组。

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

类型标识符 *数组名[常量表达式];

例如:

int *p[10];

由于[ ]比*优先级高,所以p先与[10]结合,形成p[10],这是数组形式,它再与前面的*结合,表示此数组是指针类型的,每个数组元素都可指向一个int型变量。

注意:不要写成“int (*p)[10];”,这是指向一维数组的指针变量(行指针变量)。

在定义指针数组时可初始化,例如:

char *p[5]={ “China”, “Canada”, “Singapore”, “Romania”, “Mexico” };

指针数组p中每个元素都是一个指针,指向字符串的第一个字符。数据在内存中的分配情况,如图8-1所示。

图8-1指针数组的应用

2.多级指针

指向指针的指针称为二级指针,二级以上的指针称为多级指针。多级指针定义的一般形式为:

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

指针变量名前有一个“*”,称为一级指针,简称指针。有两个星号“**”,则称为二级指针,依此类推。

二级指针变量用于存储一级指针变量的指针(即一级指针变量的地址)。

例8.10二级指针变量的定义与引用。

#include

void main()

{ int a=5,*pa,**ppa; /* 定义pa为一级指针变量,ppa为二级指针变量*/

pa=&a; /* 使pa指向a */

ppa=&pa; /* 使ppa指向pa */

printf("%d,%x,%x,%x\n",a,pa,ppa,&ppa);

printf("%d,%d,%d\n",a,*pa,**ppa);

}

运行结果如下:

5, fd8, 65d6, fda

5, 5, 5

习题8

一、选择题

1.若有定义:int x,*pb;,则以下正确的赋值表达式是______。

A) pb=&x B) pb=x C) *pb=&x D) *pb=*x

答案:

2.下列语句定义p为指向float型变量d的指针,其中正确的是______。

A)float d,*p=d;B)float *p=&d,d;

C)float d,*p=&d;D)float d,p=d;

答案:

3.指针变量p1、p2类型相同,要使p2、p1指向同—变量,哪—个语句是正确的______。

A)p2=*&p1;B)p2=**p1;C)p2=&p1;D)p2=*p1;

答案:

4.若有float a=1.5, b=3.5,*pa=&a;*pa*=3;pa=&b;,则正确的是______。

A)pa的值是1.5;B)*pa的值是4.5

C)*pa的值是3.5 D)pa的值是3.5

答案:

5.若已定义:int a[ ]={0,1,2,3,4,5,6,7,8,9},*p=a, i;,其中0≤i≤9, 则对a数组元素的引用不正确的是______。

A) a[p-a] B) *(&a[i]) C) p[i] D) *(*(a+i))

答案:

6.数组定义为int a[4Ⅱ5];,下列哪—个引用是错误的______。

A) *a B) *(* (a+2)+3) C) &a[2][3] D) ++a

答案:

7.表达式c=*p++的执行过程是______。

A)复制*p的值给c后再执行p++

B)复制*p的值给c后再执行(*p)++

C)复制p的值给c后再执行p++

D)执行p++后将*p的值复制给c

答案:

8.若有定义语句char s[4][15], *p1, **p2;int x, *y ;,下列语句中正确的是______。A)p2=s;B)y=*s;C)*p2=s;D)y=&x;

答案:

9.定义函数int *max()的确切含义是______。

A)返回整型值的函数B)返回指向整型变量的指针

C)返回指向函数max()的指针D)上面的叙述都不正确。

答案:

10.若有语句:int c[4][5], (*cp)[5];cp=c;,则对c数组元素的引用正确的是______。

A) cp+1 B) *(cp+3) C) *(cp+1)+3 D) **(cp+2)

答案:

11.若有定义:int (*ptr)(float);,其正确的含义是______。

A)ptr是指向—维数组的指针变量

B)ptr是指向int型数据的指针变量

C)ptr是指向函数的指针变量,该函数有—个float型参数,返回值是整型

D)ptr是—个函数名,该函数的返回值是指向int型数据的指针

答案:

12.以下程序的输出结果是______。

#include

void main()

{int a[10]={1,2,3,4,5,6,7,8,9,10},*p=a;

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

}

A) 3 B) 4 C) 1 D) 2

答案:

二、填空题

1.若有定义:char ch;

(1)使指针p可以指向变量ch的定义语句是_____。

(2)使指针p可以指向变量ch的赋值语句是_____。

(3)通过指针p给变量ch读入字符的scanf函数调用语句是_____。

(4)通过指针p给变量ch的赋字符的语句是_____。

(5)通过指针p输出ch中字符的语句是_____。

答案:

2.以下程序段的输出结果是_____。

int *var, ab;

ab=100; var=&ab; ab=*var+10;

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

答案:

3.以下程序的输出结果是____。

#include

void main()

{ int a[]={2,4,6},*prt=&a[0],x=8,y,z;

for(y=0; y<3; y++) z=(*(prt+y)

printf("%d\n",z);

}

答案:

习题8答案

一、选择题

1.若有定义:int x,*pb;,则以下正确的赋值表达式是______。

A) pb=&x B) pb=x C) *pb=&x D) *pb=*x

答案:A

分析:选项B中的赋值号左端是地址,右端是数值,错误;选项C中的赋值号左端是数值,右端是地址,错误;选项D是错误的,因为“*”运算符的后面只能是地址,而x是整型变量,不是地址。

2.下列语句定义p为指向float型变量d的指针,其中正确的是______。

A)float d,*p=d;B)float *p=&d,d;

C)float d,*p=&d;D)float d,p=d;

答案:C

分析:选项A中的赋值号左端是指针变量,右端是实型变量,错误;选项B中的赋值号右端的d没有定义,错误;选项D中的p不是要定义的指针变量,错误。

3.指针变量p1、p2类型相同,要使p2、p1指向同—变量,哪—个语句是正确的______。

A)p2=*&p1;B)p2=**p1;C)p2=&p1;D)p2=*p1;

答案:A

4.若有float a=1.5, b=3.5,*pa=&a;*pa*=3;pa=&b;,则正确的是______。

A)pa的值是1.5;B)*pa的值是4.5

C)*pa的值是3.5 D)pa的值是3.5

答案:C

分析:本题共有三个语句:第一个语句是定义语句,将&a赋给pa,则pa指向a;第二个语句是赋值语句*pa*=3;即a*=3;即a=a*3;即a=4.5; 第三个语句也是赋值语句,使pa指向b,即*pa是3.5。所以选项B是错误的而选项C是对的;pa是指针变量,所示选项A和D是错误的;

5.若已定义:int a[ ]={0,1,2,3,4,5,6,7,8,9},*p=a, i;,其中0≤i≤9, 则对a数组元素的引用不正确的是______。

A) a[p-a] B) *(&a[i]) C) p[i] D) *(*(a+i))

答案:D

分析:两个地址相减是普通整数,由于p的值是a,同一个地址,所以p-a是0,选项A是对的;选项B是对的,因为*(&a[i])即a[i];选项C是对的,因为p和a是同一地址,p[i]即a[i];选项D的*(*(a+i))即*(a[i])是错误的,因为“*”运算符的后面只能是地址。

6.数组定义为int a[4Ⅱ5];,下列哪—个引用是错误的______。

A) *a B) *(* (a+2)+3) C) &a[2][3] D) ++a

答案:D

分析:选项A中的*a,即a[0],即&a[0][0],正确;选项B中的*(* (a+2)+3),即*(a[2]+3),即a[2][3],正确;选项C正确;选项D错误,因为数组名是常量,++运算符只能用于变量。

7.表达式c=*p++的执行过程是______。

A)复制*p的值给c后再执行p++

B)复制*p的值给c后再执行(*p)++

C)复制p的值给c后再执行p++

D)执行p++后将*p的值复制给c

答案:A

分析:指针运算符*和自增运算符++的优先级相同,结合性自右向左,所以表达式c=*p++等价于c=*(p++),先将*P赋给c,然后p自增1。

8.若有定义语句char s[4][15], *p1, **p2;int x, *y ;,下列语句中正确的是______。

A)p2=s;B)y=*s;C)*p2=s;D)y=&x;

答案:D

分析:选项A中的p2是二级指针变量,而s是行指针,即指向长度为15的字符型一维数组,两者类型不同,不能赋值;选项B中的y是指向整型变量的指针,而*s,即s[0],亦即&s[0][0]是指向字符型变量的指针,类型不同,不能赋值;选项C中的*p2是字符型指针,而s是行指针,两者类型不同,不能赋值。

9.定义函数int *max()的确切含义是______。

A)返回整型值的函数B)返回指向整型变量的指针

C)返回指向函数max()的指针D)上面的叙述都不正确。

答案:B

10.若有语句:int c[4][5], (*cp)[5];cp=c;,则对c数组元素的引用正确的是______。

A) cp+1 B) *(cp+3) C) *(cp+1)+3 D) **(cp+2)

答案:D

分析:行指针加上一个整数仍是行指针,经*运算后变成列指针(即数组元素指针),列指针加上一个整数仍是列指针,列指针经*运算后即为数组元算。选项A中的cp+1等于c[1],是行指针,不是数组元素;选项B中的*(cp+3)等于&c[3][0],不是数组元素;选项C中的*(cp+1)+3等于&c[1][3],不是数组元素;选项D中的**(cp+2)等于c[2][0],是数组元素。

11.若有定义:int (*ptr)(float);,其正确的含义是______。

A)ptr是指向—维数组的指针变量

B)ptr是指向int型数据的指针变量

C)ptr是指向函数的指针变量,该函数有—个float型参数,返回值是整型

D)ptr是—个函数名,该函数的返回值是指向int型数据的指针答案:C

12.以下程序的输出结果是______。

#include

void main()

{int a[10]={1,2,3,4,5,6,7,8,9,10},*p=a;

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

}

A) 3 B) 4 C) 1 D) 2

答案:A

分析:*(p+2)为a[2]。

二、填空题

1.若有定义:char ch;

(1)使指针p可以指向变量ch的定义语句是_____。

(2)使指针p可以指向变量ch的赋值语句是_____。

(3)通过指针p给变量ch读入字符的scanf函数调用语句是_____。

(4)通过指针p给变量ch的赋字符的语句是_____。

(5)通过指针p输出ch中字符的语句是_____。

答案:(1)char *p=&ch; (2)p=&ch;(3)scanf("%c",p);

(4)ch=*p;(5)printf("%c",*p);

2.以下程序段的输出结果是_____。

int *var, ab;

ab=100; var=&ab; ab=*var+10;

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

答案:110

3.以下程序的输出结果是____。

#include

void main()

{ int a[]={2,4,6},*prt=&a[0],x=8,y,z;

for(y=0; y<3; y++) z=(*(prt+y)

printf("%d\n",z);

}

答案:6

分析:输出结果是第3次执行for循环体(y=2时),z=(6<8)?6:8,即z=6。补充题

一、选择题

081选择题15

以下定义语句中正确的是

A)int a=b=0 ; B)char A=65+1,b='b';

C)float a=1,*b=&a,*c=&b ; D)double a=0.0;b=1.1;

答案:

081选择题23

有以下程序

#include

main()

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

--p; y=*p; printf(“y=%d\n”,y);

}

程序的运行结果是

A)y=0 B)y=1 C)y=2 D)y=3

答案:

081选择题25

设有如下程序段

char s[20]= “Bejing”,*p;

p=s;

则执行p=s;语句后,以下叙述正确的是

A)可以用*p表示s[0]

B)s数组中元素的个数和p所指字符串长度相等

C)s和p都是指针变量

D) 数组s中的内容和指针变量p中的内容相等

答案:

081选择题32

有以下程序

#include

void fun(int *s, int nl, int n2)

{ int i,j,t;

i=nl; j=n2;

while(i

}

main()

{ int a[10]={1,2,3,4,5,6,7,8,9,0},k;

fun(a,0,3); fun(a,4,9); fun(a,0,9);

for(k=0;k<10;k++)printf("%d",a[k]); printf("\n");

}

程序运行的结果是

A)0987654321 B)4321098765 C)5678901234 D)0987651234 答案:

081选择题33

有以下程序

C++程序设计 第八章 指针和引用

C++程序设计 第8章指针和引用 在程序运行时变量和函数都存放在内存中,通过变量名来访问数据、通过函数名来调用函数都是直接访问方式。还有另一种间接访问方式就是用指针。指针的本质是内存地址。指针往往用于说明函数的形参,使实参能通过指针传递,以提高函数调用的效率。利用指针能动态地使用内存,以提高内存使用效率。指针也能用来表示数据关联,以构成复杂的数据结构。指针是C程序中最常见的类型。引用是C++扩展的新概念,主要用于函数形参和返回类型。本章将详细介绍指针和引用的概念及应用。 8.1 指针及指针变量 指针(pointer)的本质是内存地址。指针变量就是专门存储地址的一种变量。通过指针变量所存储的地址来访问数据是一种间接寻址方式。由于处理器的机器语言能支持间接寻址,所以使用指针可以达到较高的计算性能。 8.1.1 地址的概念 C++编译器对不同对象或变量按其数据类型分配合适大小的存储空间。例如为char或bool型变量分配1个字节(bytes)的存储空间,short分配2字节,int和float分配4个字节,为double型变量分配8个字节的存储空间。当程序执行时,代码和变量都加载到内存中。计算机内存被分成若干个存储单元,存储单元以字节为单位。每个存储单元都有一个固定的编号,这个编号就是内存地址。尽管一个变量可能占用多个字节空间,但都通过第一个字节的地址来访问。存放某个变量的第一个字节的地址就是该数据的首地址。 指针即内存单元的地址,而数据是内存单元中的内容(或值)。 假设在程序中说明了1个int型的变量a,其值为68。系统为变量a分配4字节的存储空间,设首地址为0X0065FDF4。通过地址0X0065FDF4就能找到变量a在内存中的存储单元,从而对变量a进行访问。0X0065FDF4就是变量a的指针。知道一个变量的地址和变量的类型就能对变量进行访问,就如同知道房间号就能找到房间,从而找到房间里的主人。 指针是一种特殊的数据类型。所有类型的变量,无论是基本类型、用户定义类型、还是这些类型的数组,在一次运行时都有确定的地址,因此它们都有指针。对于32位计算机,地址长度就是32位,因此一个指针需要4个字节,与整型int、浮点型float具有相同大小的长度。一个指针不仅有值,而且还要确定其类型,表示它能指向什么类型的数据,决定了通过它要取用多少字节作为该变量的值。

第8章指针1练习答案

指针1 选择题 1.如下程序段: int *p ,a=10 ,b=1 ; p=&a ;a=*p+b ; 执行该程序段后,a 的值为。 A. 12 B. 11 C. 10 D. 编译出错 2.若有以下定义和语句: double r=99 ,*p=&r ; *p=r ; 则以下正确的叙述是。 A. 以下两处的*p 含义相同,都说明给指针变量p 赋值 B. 在"double r=99,*p=&r;"中,把r 的地址赋值给了p 所指的存储单元 C. 语句"*p=r;"把变量r 的值赋给指针变量p D. 语句"*p=r;"取变量r 的值放回r 中 3.若有说明int *p,a;则能通过scanf语句正确给a存入数据的程序段是()。 A.p=&a; scanf(“%d”,p); B.scanf(“%d”,a); C.p=&a; scanf(“%d”,*p); D.*p=&a; scanf(“%d”,p); 4.若int x ,*pb;,则正确的赋值表达式是。 A. pb=&x B. pb=x; C. *pb=&x; D. *pb=*x 5.若有说明:int i, j=2,*p=&i;,则能完成i=j 赋值功能的语句是。 A. i=*p; B. *p=*&j; C. i=&j; D. *p=i; 6.若已定义:int a[9] ,*p=a;并在以后的语句中未改变p 的值,不能表示a[1]地 址的表达式是()。 A. p+1 B. a+1 C. a++ D. ++p 7.若有以下说明:int a[10]={1,2,3,4,5,6,7,8,9,10} ,*p=a ; 则数值为6 的表达式是( )。 A. *p+6 B. *(p+6) C. *p+=5 D. p+5 8.以下程序段的运行结果是()。 int a[10]={1,2,3,4,5,6,7,8,9,10}; int *p=&a[3],*q; q=p+2; printf(“%d”,*p+*q); A.16 B.10 C.8 D.6

C语言第八章地址与指针

1文档来源为:从网络收集整理.word 版本可编辑. 第八章 地址和指针 第一节 变量的地址和指针 1、计算机的内存是以字节为单位的一片连续的存储空间,每一个字节都有一个编号,这个编号就成为内存地址。 2、程序中定义了一个变量,c 编译系统就会根据定义中变量的类型,为其分配一定字节数的内存空间: Short int 2 Int float 4 Double 8 char 1 指针 4 图8.1 变量在内存中所占字节的地址示意图 每个变量的地址就是指该变量所占存储单元的第一个字节的地址。 3、直接存取:程序中我们对变量进行存取操作,实际上也就是对某个地址的存储单元进行操作。这种直接按变量的地址存取变量值的方式。 4、在c 语言中,还可以定义一种特殊的变量,这种变量只 a 2001 p 3001 a b x 1012 1013 1015 1016 1201 1202 1203 1204 a

1文档来源为:从网络收集整理.word 版本可编辑. 是用来存放内存地址的。 图8.2 存放地址的指针变量示意图 通过变量p 间接得到变量a 的地址,然后再存取变量a 的值的方式称为“间接存取”方式,通常变量p 指向了变量a ,变量a 是变量p 所指向的对象。 5、用来存放指针地址的变量就称作“指针变量”。 6、“变量p 指向变量a ”的含义就是指针变量p 中存放了变量a 的地址。 7、在某些场合,指针是使运算得以进行的唯一途径。 第二节 指针的定义赋值 一、 指针变量的定义和指针变量的基本类型 1、 定义指针变量的一般形式如下: 类型名 *指针变量名1,*指针变量名2…… 说明:1)类型名是基本类型。 2)*是说明符。(而在调用的时候,代表的是存储单元中的值) 3)指针变量名是用户标识符。 例:1)int *pi,*pj; pi pj 只能存放整型变量的地址 int I,*pi;double *pj; 2)p 为一个指向指针的指针变量 2002 2002 1012 1013 p p

第八章 二级c语言

第八章变量的地址和指针 变量:整 int 4B 单精度 float 4B 双精度 double 8B 存储空间:随机存放 short int a,b; float c,d; a 2B b 2B c 4B d 4B 1012 1013 1018 1019 2010 2011 2012 2013 3033 3034 3035 3036 变量的地址:该变量所占存储单元的第一个字节的 地址 &a=1012 p a *定义一个指针变量用于存放地址 4039 1012 地址就是指针 1.指针变量:存放(指向)不同地址的指针 定义:类型说明 *变量名; int *p; (指向一个整型变量) float *f;

2.给指针变量赋值 (1)int a,*p; p=&a; /*将a变量的地址赋给指针p*/ (2)初始化赋值 int a,*p=&a; 3.赋值形式: (1)赋值运算 int a,*p; p=&a; 注意:p=1000; (错误) (2)初始化赋值 int a,*p=&a; (3)把一个指针变量的值送给相同类型的另一个指针变量 int a,*pa,*pb; pa=&a; pb=pa; /*两个指针同时指向a*/ (4)把数组的首地址,送给指针变量

(数组名就表示数组的首地址) int b[5],*p; p=b; 或者 p=&b[0] (也可以指在数组中间 p=&b[2]) (5)把字符串的首地址送给字符型的指针变量 char *p; p="abcdef"; (把字符串的首地址送给p) 4.指针变量的运算 &:取地址符号 *:取内容运算符(把指针所指变量内容取出来) 优先级相同 main() {int a,*p=&a; a=5; printf("%d\n",*p); printf("%d\n",p); printf("%d\n",&p);}

计算机二级c语言第八章 指针习题

第八章指针 一、选择题 1、设有定义:int n1=0,n2,*p=&n2,*q=&n1;,以下赋值语句中与n2=n1;语句等价的是 A)*p=*q; B)p=q; C)*p=&n1; D)p=*q; 2、若有定义:int x=0, *p=&x;,则语句printf("%d\n",*p);的输出结果是 A)随机值 B)0 C)x的地址 D)p的地址 3、以下定义语句中正确的是 A)char a='A'b='B'; B)float a=b=10.0; C)int a=10,*b=&a; D)float *a,b=&a; 4、有以下程序 main() { int a=7,b=8,*p,*q,*r; p=&a;q=&b; r=p; p=q;q=r; printf("%d,%d,%d,%d\n",*p,*q,a,b); } 程序运行后的输出结果是 A)8,7,8,7 B)7,8,7,8 C)8,7,7,8 D)7,8,8,7 5、设有定义:int a,*pa=&a;以下scanf语句中能正确为变量a读入数据的是 A)scanf("%d",pa) ; B)scanf("%d",a) ; C)scanf("%d",&pa) ; D)scanf("%d",*pa) ; 6、设有定义:int n=0,*p=&n,**q=&p;则以下选项中,正确的赋值语句是 A)p=1; B)*q=2; C)q=p; D)*p=5; 7、有以下程序 void fun(char *a,char *b) { a=b; (*a)++; } main () { char c1='A', c2='a', *p1, *p2; p1=&c1; p2=&c2; fun(p1,p2); printf("%c%c\n",c1,c2); }程序运行后的输出结果是 A)Ab B)aa C)Aa D)Bb 8、有以下程序 #include main() { printf("%d\n", NULL); } 程序运行后的输出结果是 A)0 B)1 C)-1 D)NULL没定义,出错 9、已定义以下函数 fun(int *p) { return *p; } 该函数的返回值是 A)不确定的值 B)形参p中存放的值

第八章地址和指针

第八章地址和指针 8.1变量的地址和指针 在程序中变量实际上代表了内存中的某个存储单元。那么C是怎样存取这些单元的数据内容的呢? 我们知道计算机的内存是以字节为单位的一片连续的存储空间,每个内存单元都有一个唯一的编号,我们将其称为“内存地址”。计算机对数据的存取操作都是依赖于内存地址进行的。因为计算机的内存空间是连续的,所以内存中的地址空间也是连续的,并且用二进制数据来表示,为了方便和直观,我们将用十进制数据进行描述。 若在程序中定义了一个变量,C编译系统就会自动根据变量的类型,为其分配一定字节数量的存储空间。如int型2个字节,float型4个字节,double型8个字节,char型1个字节等。此后,这个变量的内存地址也就唯一的确定了。 一般情况下,我们在程序中只要给出变量名,不需要知道每个变量在内存中的具体地址,变量与地址之间的联系由C编译系统来完成。程序中我们对变量进行存取操作,实际上就是对变量地址的存储单元进行操作。这种直接按照变量地址进行存取的操作方式称为“直接存取”方式。 在C语言中我们还可以定义一种特殊的变量,这种变量只是用于存放内存变量地址的。如:p93 图8.2 这种通过变量p间接得到变量a的地址,然后再存取变量a的值的方式称为“间接存取”的方式。这种用来存放地址的变量称为“指针变

量”或“指针”。 由此我们可以知道,在C语言中,地址是指变量在内存中的存放的位置,即存放该变量的内存单元的名字。而指针是指一个变量,在该变量中存放的是其指向的那个变量在内存存储单元的地址。也就是说,变量的地址就可以理解为指针。 在C语言中,指针被广泛使用,他可以使程序简洁并高效运行,但使用不当就会产生意料不到的严重后果。因此,正确使用和掌握指针是十分必要的。 8.2 指针变量的定义和基本类型 定义指针变量的形式: 类型名*指针变量名1,*指针变量名2,……; 例如: int *pi,*pj; float *i,*j,*k; double *l,*m,*n; char *c,*s; 在每个变量前面的星号*是一个指针说明符,用来说明该变量是指针类型。变量前面的星号*不可以省略。指针变量名前面的类型定义是说明指针指向的数据类型。 另外,我们还可以定义一个指向指针的指针变量。定义形式为: 类型名**指针变量名1,**指针变量名2,……;

第8章 善于利用指针(1)

内存管理指针的基本概念指针应用实例指针作函数参数第8章指针(1)

复习回顾 上次课的内容: ◆局部变量和全局变量 ◆变量的作用域 ◆变量的生存期 ◆声明与定义 ◆内部函数 ◆外部函数◆你开始习惯写函数了吗? 2012是如何实现的?假定造成世界末日的上帝是一个程序员,作为一名合格的程序员,他绝不应该写出类似于“摧毁地球”这样的程序,而应该写一个“摧毁(行星)”的函数,然后把地球作为参数传进去!

C语言新手的晋级之路 第一步:萧规曹随 ◆在这一步要求按照教材或讲义上的程序实例进行原样 输入,运行一下程序看是否正确。 ◆在这一步,掌握C语言编程软件的使用方法(包括新 建、打开、熟练输入、编辑、保存、关闭C程序); 初步记忆新学章节的知识点;养成良好的编程风格( 是讲义提倡的而不是教材上的) ◆难点:小心数字1和字母l,字母o和数字0,中英文标 点符号的区别

C语言新手的晋级之路 第二步:移花接木 ◆在第一步输入的C程序的基础上进行试验性的修改, 运行一下程序看一看结果发生了什么变化,分析结果变化的原因,加深新学知识点的理解。 ◆可与第一步同步进行,“输入”可加深记忆,“修改 ”可加深理解,二者相辅相成,互相促进。 ◆友提,一次进行一处修改即可,免得把自己改晕了。

C语言新手的晋级之路 第三步:无中生有 ◆面对教材的例子题目,不参考教材,自己从头开始编 写程序。看能否写出正确运行的代码。 ◆初学者易犯的错误:scanf格式控制和输入不匹配或把变量 名当地址作参数,使用未定义的变量、漏掉或多写“;”、“{” 与“}”、“(”与“)”不匹配,控制语句(选择、分支、循环)的格式不正确,调用库函数没有包含相应头文件,调用未声明 的函数、调用函数时实参和形参不匹配、数组边界越界等等 ◆要学会看编程工具的错误信息提示:双击错误提示光标可 跳转到发生错误的行,如果该行没有错误就往前查找。错误要一 个一个修改,每改完一次编译一下程序。

第8章-指针练习题

指针思考题 一、填空题 【1】下面函数要求用来求出两个整数之和,并通过形参传回两数相加之和值,请填空。 int add( int x, int y, ) { =x+y;} 【2】若有定义: char ch; (1) 使指针p 可以指向变量ch的定义语句是。 (2) 使指针p指向变量ch的赋值语句是。 (3) 通过指针p给变量ch读入字符的scanf函数调用语句是。 (4) 通过指针p 给变量ch赋字符A的语句是。 (5) 通过指针p输出ch中字符的语句是。 (6) 在16位微机上,指针变量p在内存中所占字节数是,变量ch在内在所占字 节数是。 二、选择题 【3】若有说明:int i,j=7,*p=&i;则与i=j;等价的语句是()。 A.i=*p; B.*p=*&j; C.i=&j; D.i=**p; 【4】若有定义:int x,*pb;则正确的赋值表达式是()。 A.pb=&x B.pb=x C. *pb=&x D.*pb=*x 【5】对于类型相同的指针变量,不能进行的运算是()。 A.< B. = C. + D. – 【6】以下程序的输出结果是()。 A.23 B. 24 C. 25 D. 26 Void fun ( int *x) { printf(%d\n”,++*x); } main( ) { int a=25; fun (&a); } 【7】以下程序的输出结果是()。 A.6 B. 7 C. 8 D. 9 main() { int k=2,m=4,n=6; int *pk=&k,*pm=&m,*p; *(p=&n)=*pk*(*pm); printf("%d\n",n); } 【8】以下程序的输出结果是()。 A.100 B. 50 C. 101 D.200 main() { int *v,b; v=&b; b=100;

指针1

指针 一、指针概述 1. 地址 C++程序中每一个实体,如变量、数组和函数等,都要在内存中占有一个可标识的存储区域。每一个存储区域由若干个字节组成,在内存中,每一个字节都有一个“地址”,一个存储区的“地址”指的是该存储区中第一个字节的地址。 2.指针 指针就是存储区域的地址。一个地址指向一个程序实体的存储空间。 直接访问:通过变量名或地址访问程序中一个实体的存储空间的方式(其实通过变量名访问也就是通过地址访问)。 间接访问:把一个变量的地址放在另一个变量中。 3.指针变量 专门用来存放地址的变量就叫指针变量,需要专门加以定义。 二、指针的类型与指针的定义 指针也是具有类型的。指针的类型就是它所指向的变量的类型。例如,一个指向int型的指针,一个指向一维数组的指针。 在使用一个指针变量之前,先要用声明语句对其进行定义。例如:int *p; 定义了一个指向整型数据的指针变量p。即p是一个存放整型变量地址的变量。 应当特别注意的是,定义一个指针变量必须用符号“*”,它表示其后的变量为指针变量,指针变量为p,而不是*p。 要想使一个指针变量指向一个变量,必须将变量的地址赋给指针变量。例如:

int *p, i=3; p=&i; 指针变量也可以定义为指向实型、字符型以及其它类型的变量。如: float *p ; char *q ; 三、指针运算符 在C++语言中,有两个有关指针的运算符: &:为取地址运算符,&x的值为x的地址。 * :指针运算符,或称指向运算符,也称间接运算符,*p代表p 所指向的变量。如: int a=15, *p; p=&a; cout<

第8章 指针

第8章指针 1. 单项选择题 (1)指针 pstr所指字符串的长度为D。char *pstr="\t\"1234\\abcd\n" A.15 B.14 C.13 D.12 (2)若有定义int a[4][6];则能正确表示a数组中任一元素a[i][j](i,j 均在有效范围内)地址的表达式A。 A.&a[0][0]+6*i+j B.&a[0][0]+4*j+i C.&a[0][0]+4*i+j D.&a[0][0]+6*j+i (3)以下程序段的输出结果为D。 char astr[5]="1234"; char *pstr=astr; printf("%c",pstr[1]-'0'); A.1 B. 2 C. ASCII码值为 1 的字符 D. ASCII 码值为 2 的字符 (4)下述程序段的输出结果为D。 char astr[]="abcde"; char *pstr=&astr[5]; while(--pstr>=astr) putchar(*pstr); putchar('\n'); A. abc B. cba C. abcde D. edcba (5)若有定义 int a=1,*b,c;,以下不正确的是 A 。 A. b=a B. b=&a C. b=&a,c=*b D. c=a (6)以下程序段的运行结果为 C 。 intnum[]={1,2,3,4,5,6,7,8,9},*pnum=&num[2]; pnum++; ++pnum; printf("%d\n",*pnum); A. 3 B. 4 C. 5 D. 6 (7)以下程序段的运行结果为 B 。 char *pstr="My name is Tom"; int n=0;

C二级 第8章 指针

1.以下定义语句中正确的是 A) int a=b=0; B) char A=65+1,b='b'; C) float a=1,*b=&a,*c=&b; D) double a=0.0; b=1.1; 参考答案:B 【解析】A选项语句中b变量还没有定义不能直接用于给a变量赋值?C选项语句中*b?*c表示的是一个实型变量的地址,不能再将&b赋值给指针型变量c?D选项语句中a=0.0后面应该为逗号,不能是分号? 2.有以下程序 #include void f(int *p,int *q); main() { int m=1,n=2,*r=&m; f(r, &n); printf("%d,%d",m,n); } void f(int *p,int *q) { p=p+1; *q=*q+1; } 程序运行后的输出结果是 A) 2,3 B) 1,3 C) 1,4 D) 1,2 参考答案:B 【解析】在f(int *p,int*q)函数中,执行p=p+1是将p所对应的地址加1,而*q=*q+1是将q所指向的n的地址所对应的值加1,所以m的得知所对应的值没有变,而n的值则为3了。因此B选项正确。 3.以下叙述中正确的是 A) 如果p是指针变量,则&p是不合法的表达式 B) 如果p是指针变量,则*p表示变量p的地址值 C) 在对指针进行加、减算术运算时,数字1表示1个存储单元的长度 D) 如果p是指针变量,则*p+1和*(p+1)的效果是一样的 参考答案:C 【解析】B选项中,如果p是指针变量,则*p表示变量p所指向的地址的值;A选项中,如果p是指针变量,则&p表示变量p的地址;D选项中,如果p是指针变量,*p+1表示将p所指的值加上1,而*(p+1)表示的是先将指针右移一位再取所指向变量的值。因此C选项正确。 4.以下叙述中正确的是 A) 基类型不同的指针变量可以相互混用 B) 函数的类型不能是指针类型 C) 函数的形参类型不能是指针类型 D) 设有指针变量为double *p,则p+1 将指针p移动8个字节 参考答案:D 【解析】B选项中,所谓函数类型是指函数返回值的类型。在C语言中允许一个函数的返回值是一个指针(即地址),这种返回指针值的函数称为指针型函数;C选项中,函数的参数不仅可以是整型、实型、字符型等数据,还可以是指针类型;A选项中,虽然不同基类型的指针变量占用字节数是相同的,但是不能混用。因此D选项正确。 5.如果定义 float a[10], x; 则以下叙述中正确的是

第8章-指针

第八章 一、选择题。 8.1若有定义:int x,*pb;则正确的赋值表达式是()。 A) pb=&x B)pb=x C)*pb=&x D)*pb=*x 8.2 若有以下程序: #include main() { printf(“%d\n”,NUUL); } 程序的输出结果是()。 A)因变量无定义输出不定值B)0 C)-1 D)1 8.3若有以下程序: #include void sub(int x,int y,int *z) { *z = y-x;} main() { int a,b,c; sub(10,5,&a); sub(7,a,&b); sub(a,b,&c) printf(“%d,%d,%d\n”,a,b,c); } 程序的输出结果是()。 A)5,2,3 B)-5,-12,-7 C)-5,-12,-17 D)5,-2,-7 8.4若有以下程序: #include main() { int k=2,m=4,n=6,*pk=&k,*pm=&m,*p; *(p=&n) =*pk*(*pm); printf(“%d\n”,n); } 程序的输出结果是()。 A)4 B) 6 C) 8 D) 10 8.5若指针p已正确定义并指向如图8.8所示储存单元: a[0] a[1] a[2] a[3] a[4] p↑ 图8.8 指针p指向示意图 则执行语句*p++;后,*p的值是()。 A)20 B)30 C)21 D)31 8.6若指针p已正确定义并指向如图8.8所示存储单元,则表达式*++p的值是()。 A)20 B)30 C)21 D)31 8.7若指针p已正确定义并指向如图8.8所示存储单元,则表达式++*p的值是()。 A)20 B)30 C)21 D)31 8.8若有以下程序: #include void prtv(int *x)

C语言第八章 地址和指针

第八章 地址和指针 第一节 变量的地址和指针 1、计算机的内存是以字节为单位的一片连续的存储空间,每一个字节都有一个编号,这个编号就成为内存地址。 2、程序中定义了一个变量,c 编译系统就会根据定义中变量的类型,为其分配一定字节数的内存空间: Short int 2 Int float 4 Double 8 char 1 指针 4 图8.1 变量在内存中所占字节的地址示意图 每个变量的地址就是指该变量所占存储单元的第一个字节的地址。 3、直接存取:程序中我们对变量进行存取操作,实际上也 a 2001 p 3001 a b x 1012 1013 1015 1016 1201 1202 1203 1204

就是对某个地址的存储单元进行操作。这种直接按变量的地址存取变量值的方式。 4、在c 语言中,还可以定义一种特殊的变量,这种变量只是用来存放内存地址的。 图8.2 存放地址的指针变量示意图 通过变量p 间接得到变量a 的地址,然后再存取变量a 的值的方式称为“间接存取”方式,通常变量p 指向了变量a ,变量a 是变量p 所指向的对象。 5、用来存放指针地址的变量就称作“指针变量”。 6、“变量p 指向变量a ”的含义就是指针变量p 中存放了变量a 的地址。 7、在某些场合,指针是使运算得以进行的唯一途径。 第二节 指针的定义赋值 一、 指针变量的定义和指针变量的基本类型 1、 定义指针变量的一般形式如下: 类型名 *指针变量名1,*指针变量名2…… 说明:1)类型名是基本类型。 2)*是说明符。(而在调用的时候,代表的是存储单元中的值) 3)指针变量名是用户标识符。 2002 2002 1012 1013 p a p

C语言知识第8章1-王厚财

复习: 1.数值型数组与字符型数组的定义 2.数值型数组的赋初值与字符型数组的赋初值以及字符串的赋值 3.对于数值型数组的操作 4.对于字符串的操作及函数 5.排序 讲授新课: 第8章 指 针 指针是C语言中广泛使用的一种数据类型。 8.1 地址与指针 8.1.1数据在内存中的存储 计算机的内存是以字节为单位的一片连续的存储空间,每一个字节都有一个确定的编号,这个编号就是内存地址。 a x

见图8.1所示,内存的编号从0开始,连续进行编号。在实际处理中,地址通常采用十六进制数形式。 8.1.2 变量的地址 在C程序中定义了一个变量,C编译系统就会根据定义中变量的类型,为其分配一定字节数的内存空间,所分配存储空间的首地址称为此变量的地址。所分配存储空间中的数据就是这个变量的值,也就是存储单元的内容。 8.1.3 变量的存取方式 1.直接存取 一般情况下,我们在C程序中只需指出变量名就可以对变量进行存取操作,实际上也是对某个地址的存储单元进行操作。这种直接按变量的地址存取变量值的方式称为“直接存取”方式。 2.间接存取 与“直接存取”方式相对应的是“间接存取”方式。在C语言中,我们通过定义一种特殊的变量(即指针变量,一会我们将详细叙述;同时,为了叙述方便,我们将前面章节中定义的变量称为普通变量。)用于存放内存单元的地址,然后根据这种特殊的变量的内容(里面存放的是地址值)去访问相应的存储单元。这种方式称为“间接存取”方式。 “--- ”只是一种示意,形似“指针”。用来存放地址值的变量称为指针变量,“变量p指向了变量a”的含义是指针变量p中存放了变量a的地址。 8.1.4 指针变量 如果一个变量中存放是地址值,那么称这个变量为指针变量。常把指针变量简称为指针。定义指针的目的是为了通过指针去访问内存单元。

C语言程序设计(第3版)何钦铭 颜 晖 第8章 指针

第8章指针 【练习8-1】如果有定义”int m, n = 5, *p = &m;”与m = n等价的语句是 B 。A.m = *p; B. *p = *&n; C. m = &n; D. m = **p; 解答: A:p是指向m的指针变量,所以*p等价于m。即m=m。 B:&n是n的地址,*&n是n的值,即把n的值赋给p指向的值m。即m=n。 C:&n是n的地址。即把n的地址赋给m。 D:**p是指p指向的指针所指向的值,在此无意义。 故选B。 【练习8-2】调用函数求两个数的和与差:计算输入的两个数的和与差,要求自定义一个函数sum_diff(float op1,float op2, float *psum, float *pdiff),其中op1和op2是输入的两个数,*psum 和*pdiff 是计算得出的和与差。 解答: #include<> void sum_diff(float op1,float op2,float *psum,float *pdiff); int main(void) { float op1,op2,sum,diff; printf("Input op1 and op2: "); scanf("%f%f",&op1,&op2); sum_diff(op1,op2,&sum,&diff); printf("%f+%f=%f;%f-%f=%f \n",op1,op2,sum,op1,op2,diff); return 0; } void sum_diff(float op1,float op2,float *psum,float *pdiff) { *psum=op1+op2; *pdiff=op1-op2; } 【练习8-3】两个相同类型的指针变量能不能相加为什么 解答: 不能。因为指针变量是一种特殊的变量,指针变量的值存放的是所指向变量的地址,两个地址相加并不能保证结果为一个有效的地址值,因而在 C 语言中指针变量相加是非法的。 【练习8-4】根据表所示,这组数据的冒泡排序其实循环到第 6 遍(即n-2)时就已经排好序了,说明有时候并不一定需要n-1 次循环。请思考如何改进冒泡排序算法并编程实现(提示:当发现一遍循环后没有数据发生交换,说明已经排好序了)。 解答:

第八章 文 件

第八章文件 一、单项选择题 1.C语言中,文件由(A)。 A.字符(字节)序列组成B.记录组成 C.数据行组成D.数据块组成 2.若文件型指针fp中指向某文件的末尾,则函数feof(fp)的返回值是(C)。 A.0 B.-1 C.非零值D.NULL 3. 下列语句将输出(B) #include printf(“%d %d %d”, NULL,’\0’,EOF); A. 0 0 1 B. 0 0 –1 C. NULL EOF D. 1 0 EOF 4.下列语句中,将fp定义为文件型指针的是(B)。 A.FILE fp; B.FILE *fp;C.file fp; D.file *fp; 5. 定义FILE *fp; 则文件指针fp指向的是(D)。 A. 文件在磁盘上的读写位置 B. 文件在缓冲区上的读写位置 C. 整个磁盘文件 D. 文件类型结构体 6. 缓冲文件系统的缓冲区位于(C )。 A. 磁盘缓冲区中 B. 磁盘文件中 C. 内存数据区中 D. 程序中 7.以“只读”方式打开文本文件a:\aa.dat,下列语句中哪一个是正确的( D)。 A、fp=fopen(”a:\aa.dat”,”ab”); B、fp=fopen(”a:\aa.dat”,”a”); C、fp=fopen(”a:\aa.dat”,”wb”); D、fp=fopen(”a:\aa.dat”,”r”); 8. 以“追加”方式打开文本文件a:\aa.dat,下列语句中哪一个是正确的( B)。 A、fp=fopen(”a:\aa.dat”,”ab”); B、fp=fopen(”a:\aa.dat”,”a”); C、fp=fopen(”a:\aa.dat”,”r+”); D、fp=fopen(”a:\aa.dat”,”w”); 9. 如果二进制文件a.dat已存在,现要求写入全新的数据,应以什么方式打开(A)。 A. “w” B. “wb” C. “w+” D. “wb+” 10. 为读写建立一个新的文本文件a:\aa.dat,下列语句中哪一个是正确的( B)。 A、fp=fopen(”a:\aa.dat”,”ab”); B、fp=fopen(”a:\aa.dat”,”w+”); C、fp=fopen(”a:\aa.dat”,”wb”); D、fp=fopen(”a:\aa.dat”,”rb+”); 11.以读写方式打开一个已有的二进制文件filel,并且定义FILE *fp,下面fopen函数正确的调用方式是(B )。 A.fp=fopen (“file1”, ”r”) B.fp=fopen (“file1”, ”rb+”) C.fp=fopen (“file1”, ”rb”) D.fp=fopen (“file1”, ”w b+”) 12.标准库函数fputs (p1,p2)的功能是(C)。 A.从p1指向的文件中读一个字符串存入p2指向的内存 B.从p2指向的文件中读一个字符串存入p1指向的内存 C.从p1指向的内存中读一个字符串写到p2指向的文件中 D.从p2指向的内存中读一个字符串写到p1指向的文件中

第八章 指针

第八章指针 【本章要求】 1、指针的声明、定义方法以及通过指针变量引用存储单元中的内容 2、指针作为函数参数,地址传递情况下,函数实参的变化 3、用指针指向函数,并通过指针调用该函数 4、一维数组和字符串中元素地址的计算方法,以及通过指针引用这些元素 5、二维数组中元素的计算方法,以及通过指针数组引用其中元素的方法 6、通过命令行方式调用main函数 7、内存的动态分配和释放 8.1 指针的基本概念 如果在程序中定义了一个变量,在编译时就给这个变量分配内存单元。系统根据程序中定义的变量类型,分配一定长度的空间。内存区的每一个字节有—个编号,这就是“地址”,它相当于旅馆中的房间号。 在程序中一般是通过变量名来对内存单元进行存取操作的。程序经过编译以后己经将变量名转换为变量的地址,对变量值的存取都是通过地址进行的。 按变量地址存取变量值的方式称为“直接访问”方式。 还可以采用另一种称之为“间接访问”的方式,将变量i的地址存放在另一个变量中。按C 语言的规定,可以在程序中定义整型变量、实型变量、字符变量等,也可以定义这样一种特殊的变量,它是存放地址的。 假设我们定义了一个变量i_pointer,用来存放整型变量的地址,它被分配为3010、3011字节。可以通过下面语句将i的地址(2000)存放到i_pointer中。 i_pointer = &i; 这时,i_pointer的值就是2000,即变量i所占用单元的起始地址。要存取变量i的值,也可以采用间接方式;先找到存放“i的地址”的变量,从中取出i的地址(2000),然后到2000、2001字节取出i的值(3)。 所谓“指向”就是通过地址来体现的。i_pointer中的值为2000,它是变量i的地址,这样就在i_pointer和变量i之间建立起一种联系,即通过i_pointer能知道i的地址,从而找到变量i的内存单元。 在C语言中,将地址形象化地称为“指针”。意思是通过它能找到以它为地址的内存单元(例如根据地址2000就能找到变量i的存储单元,从而读取其中的值)。一个变量的地址称为该变量的“指针”。例如,地址2000是变量i的指针。如果有一个变量专门用来存放另一变量的地址(即指针),则它称为“指针变量”。指针变量的值(即指针变量中存放的值)是指针(地址)。 8.2 指针变量 变量的指针就是变量的地址。存放变量地址的变量是指针变量,用来指向另一个变量。为了表示指针变量和它所指向的变量之间的联系,在程序中用“*”符号表示“指向”。 - 93 -

第八章:善于利用指针

南京信息工程大学滨江学院实验(实习)报告 实验(实习)名称指针实验(实习)日期 2011.12 指导教师宣文霞 专业实验班年级大一班次4 班姓名王雅婷学号 20112335052 Eg8-1: 输入两个整数,并使其从大到小输出,用指针变量实现数的比较。 (1)源程序: #include void main() { int *p1,*p2,*p,a,b; scanf("%d,%d",&a,&b); p1=&a; p2=&b; if(a void swap(int *p1, int *p2) { int p; p=*p1; *p1=*p2; *p2=p; } void main() { int a,b; int *p,*q; scanf("%d,%d",&a,&b); p=&a; q=&b;31 if(a

(3)结果输出: (4)如果将swap 函数修改为如下形式,分析如何调试和修改? void swap(int *p1, int *p2) { int *p; *p=*p1; *p1=*p2; *p2=*p; } Eg8-3:用指针法输入12 个数,然后按每行4 个数输出。 (1)算法分析:定义一个整型数组和一个整型指针,这样通过数组就可以静态分配内存空间,存储数据;然后将指针与数组相关,使指针指向与数组相同的首地址处,这样就可以通过指针或者数组都可以对存储空间加以操作。 (2)源程序: #include void main() { int j,k,a[12],*p ; p=a; //使指针p 指向与数组a 相同的首地址处 for(j=0;j<12;j++) scanf("%d",p++); //移动P 的位置,输入数据 p=a; //指针重定位 for(j=0;j<12;j++) { if(j%4==0) printf("\n"); //按每行4 个数输出 printf("%4d",*p++); } printf("\n"); } (3)输入数据:0 1 2 3 4 5 6 7 8 9 10 11

操作系统第八章课后习题

1.目前常用的外存有哪几种组织方式? 答;(1)连续组织方式。为每一个文件分配- -组位置相邻接的盘块,由此形成的文件物理结构是顺序式的文件结构。 (2)链接组织方式。为每个文件分配一组位置离散的盘块,通过给每个盘块设置一个指针,将属于同-一个文件的盘块链接在一起,链接的顺序和文件的逻辑页的顺序一致。由此形成的文件物理结构是链接文件。 (3)索引组织方式。为每个文件分配- -组位置离散的盘块,为每个文件建立一个物理结构的索引表,记录分配给该文件的物理盘块,以及这些盘块和文件逻辑页顺序的对应关系。由此形成的文件物理结构是索引文件。 2.由连续组织方式所形成的顺序文件的主要优缺点是什么?它主要应用于何种 场合? (1)连续组织方式所形成的顺序文件的主要优点①顺序访问容易②顺序访问速度快 (2)连续组织方式所形成的顺序文件的主要缺点①要求为一个文件分配连续的存储空间 ②必须事先知道文件的长度;③不能灵活地删除和插入记录 ④对于那些动态增长的文件,由于事先很难知道文件的最终大小,因而很难为分配空间,而即使事先知道文件的最终大小,在采用预分配存储空间的方法时也会使大量的存储空间长期空闲。 (3)主要适用场合:连续组织方式所形成的顺序文件是一种最简单、最常用的文件组织方法,它适用于许多资料处理的场合,如磁带文件,打印文件都是常用的顺序文件。 3.在链接式文件中常用哪种链接方式?为什么? 答:链接方式分为隐式链接和显式链接两种形式。隐式链接是在文件目录的每目录项中,都含有指向链接文件第一个盘块和最后一个盘块的指针。显式链接贝把用于链接文件各物理块的指针,显式地存放在内存的一张链接表中。 4.在文件分配表中为什么要引入“簇”的概念?以“簇”为基本的分配单位有什么好处? (1)引入“簇”的原因:为了适应磁盘容量不断增大的需要,在进行盘块分配时不再以盘块而是以簇(Cluster)为基本单位。一个簇应包含扇区的数量与磁盘量的大小直接有关。 (2)以簇作为基本分配单位的好处:能应磁盘容量不断增大的情况,还可以减少FAT 表中的项数(在相同的磁盘容量下,FAT表的项数是与簇的大小成反比),使FAT 表占用更少的存储空间,并减少访问FAT表的存取开销。 5.简要说明为什么要从FAT12发展为FAT16?又进一步要发展为FAT32? 答:(1)从FAT12发展为FAT16的原因:FAT12 表中的表项有限制,亦即最多只允许4096个。这样,随着磁盘容量的增加。必定会引起簇的大小和簇内碎片也随之增加。要想增加FAT 表中的表项数,就必须增加FAT 表的位数(宽度)如果我们将FAT表项位数增至16位,最大表项数将增至65536 216 )个,此时便能将一个磁盘分区分为65536 (216 )个簇。 (2)从FAT16发展为FAT32的原因:由于FAT16 表的长度只有65535项,随着磁盘容量的增加,簇的大小也必然会随之增加,为了减少簇内零,也就应当增加FAT 表的长度,为此需要再增加FAT 表的宽度,这样也就由FAT16演变为FAT32

相关文档
最新文档