第 8 章 指针

24
第8第 第第

Upload: jonah-morris

Post on 02-Jan-2016

90 views

Category:

Documents


8 download

DESCRIPTION

第 8 章 指针. 8.1 指针的概念 8.2 指向简单变量的指针 8.3 指向数组的指针变量 8.4 指向字符串的指针变量 8.5 指针作为函数参数 8.6 指向结构体的指针变量 8.7 应用实例 本章小结. 8.1 指针的概念. 指针,也就是内存地址。 指针变量是用来存放这些内存地址的变量。 不同类型指针变量所占用的存储单元长度是相同的 . 直接访问方式 : 根据变量名实现对存储空间的访问。 间接访问方式 : 通过存放地址的 指针 变量实现对存储空间的访问。. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 第 8 章   指针

第 8 章 指针

Page 2: 第 8 章   指针

8.1 指针的概念8.2 指向简单变量的指针8.3 指向数组的指针变量8.4 指向字符串的指针变量8.5 指针作为函数参数8.6 指向结构体的指针变量8.7 应用实例本章小结

Page 3: 第 8 章   指针

8.1 指针的概念

• 指针,也就是内存地址。• 指针变量是用来存放这些内存地址的变量。• 不同类型指针变量所占用的存储单元长度

是相同的 .

• 直接访问方式 : 根据变量名实现对存储空间的访问。

• 间接访问方式 : 通过存放地址的指针变量实现对存储空间的访问。

Page 4: 第 8 章   指针

• 如果将变量 x 的地址 2060 存放到另一个变量 p 中,即 p 的值为2060 ,这样通过变量 p 可以找到变量 x 的地址,从而找到 x 的值。存放地址的变量 p 就是指针变量。可以形象地说, p 指向 x 。

Page 5: 第 8 章   指针

• "*" 是指针运算符,或称为“间接访问”运算符。 *p 表示指针变量 p 所指向的变量。若要改变 x 变量的值,也可通过改变 *p 的值来实现。如执行 *p = 47 ;则此时 x=47 。

• "&" 也是一个指针运算符,称为取地址运算符。如为了让指针 p 指向变量 x ,可执行 p = &x ,此时变量 x 的地址即存入了指针 p中。

• 注意,指针变量只能存放地址值,不要将一个整型数据赋给一个指针变量。

Page 6: 第 8 章   指针

8.2 指向简单变量的指针

• 指针变量也必须先定义后使用。• 格式如下:

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

例如: int *p1, p2;

则 p1 是指针变量,而 p2 是整型变量。

Page 7: 第 8 章   指针

例 8-1 :通过指针变量访问变量。main( ){int a, b, *p1, *p2;

float x, y, *q1, *q2; a=123; b=45;x=1.25; y=-0.98;p1=&a; p2=&b;q1=&x;q2=q1;printf("\na=%d, b=%d\n", a, b );printf("*p1=%d, *p2=%d\n", *p1, *p2 ); printf("x=%f, y=%f\n", x, y );printf("*q1=%f, *q2=%f\n", *q1, *q2 );

}

Page 8: 第 8 章   指针

8.3 指向数组的指针变量

• 任何可通过数组下标完成的操作也可通过指针完成。

• 然而它们之间也存在细微但很重要的区别。一般来讲,使用指针速度更快,程序更紧凑。

Page 9: 第 8 章   指针

8 。 3 。 1 指向一维数组的指针变量

• 指针变量可以指向数组或数组元素,即把数组的起始地址或某一元素的地址存放到一个指针变量中。例如:定义指针 p 指向一维整型数组 a[5] 。可进行如下说明:

int a [5];int *p;

• 注意,不能定义成 int *p[5];

• 如果这样定义,就表示定义了一个指针数组。它有 5 个元素, p[0] 、 p[1] 、 p[2] 、 p[3] 、 p[4] ,每个元素都指向整型变量。

Page 10: 第 8 章   指针

• 如果数组为 int型,则指针变量亦应指向 int型。• 执行语句: p = a ; 或 p = &a[0];均可以使指针p 指向数组a的第1个元素a[0]。• C语言规定,数组名代表数组的首地址,也就是第一个元素的地址。此外,p+1指向下一个元素,p+i 指向p后的第 i个元素 a[i]。• 无论某个数组的元素占据多少内存字节( 即元素长度,设为 len ),当指针p指向其中一个元素时,p+1均是指向它的下一个元素,而不是p+len。• 可见,a[i], *(a+i), *(p+i) 都是等价的。

Page 11: 第 8 章   指针

例 8-2 :用三种方法输出数组元素。

main ( ){ static int a[5]={5, 4, 3, 2, 1 };int i, *p = a;for ( i = 0; i < 5; i++ )printf (" %d, %d, %d \n ", a[i], *(a+i), *(p+i ) );}运行结果:5, 5, 54, 4, 43, 3, 32, 2, 21, 1, 1

Page 12: 第 8 章   指针

例 8-3 :输出数组的所有元素。

main ( ){ int a[5], *p, i ;for ( i = 0; i < 5; i++ )scanf ("%d", a + i );for ( p = a; p < a+5; p++ )printf ("%4d ", *p );}运行结果: 1 3 5 7 9↙ 1 3 5 7 9

说明:指针变量和数组名有区别,指针变量是一个变量,可以改变其值,而数组名是数组首地址,是一个地址常量,不能对它赋值。

Page 13: 第 8 章   指针

8 。 3 。 2 指向多维数组的指针变量

• C 语言将二维数组定义时的行数和列数分别用两个方括号分开,如 int a[4][3] ;,目的是把二维数组看作是一种特殊的一维数组,它的元素又是一个一维数组。

• 如,把 a 看作是由四个元素a[0] 、 a[1] 、 a[2] 、 a[3] 组成的一维数组,而每个元素 a[i]( i=0,1,2,3 ) ,又都是具有 3个元素的一维数组。

Page 14: 第 8 章   指针

例 8-5 :输出数组 int a[4][3] 中的第3 行的所有元素。

main ( ){ static int a[4 ][3]= {{1,2,3}, {4,5,6},

{7,8,9}, {10,11,12}};int *p;for ( p = a[2 ]; p < a[2]+3; p++)printf ("%4d", *p );}

运行结果: 7 8 9

Page 15: 第 8 章   指针

例 8-8 :用指针输出二维数组的各元素。

#include <stdio.h>#define M 4#define N 3#define L M*Nmain ( ){ int a[M][N], *p=a[0], i; for ( ; p < a[0]+L; p++ ) /* 从键盘上输入 L 个数据 */scanf ( "%d", p );for ( i = 0; i < M; i++ ){ p = a[i]; /* 取第 i 行的首地址 */

for( ; p < a[i] + N; p++ ) /* 输出第 i 行的 n 个元素 */

printf ("%5d", *p ) ; printf ( "\n" ); /* 换行 */

}}

Page 16: 第 8 章   指针

8.4 指向字符串的指针变量

• 在 C 语言中,字符串可以用字符数组实现。其实,字符串还可以用字符指针实现,而且字符指针更方便、简洁。

• 例如:char string[ ] = "this is a string!";

char *pstr = "that is a book!";

Page 17: 第 8 章   指针

例 8-10 :编写字符串复制函数strcpy (s1, s2 ) 。

• 用数组方法void strcpy ( char s1[ ],char s2[ ] ){ int i = 0; while ( s2[i] != '\0' ) { s1[i] = s2[i]; i++; } s1[i]=0; /* 补上串结尾符 */}

Page 18: 第 8 章   指针

• 用指针方法void strcpy ( char *p , char *q ){ while ( *q != '\0' ) { *p = *q; p++; q++; } *p=0; /* 补上串结尾符 */}

Page 19: 第 8 章   指针

例 8-12 :分别用字符指针和字符数组表示字符串。

#include <stdio.h>main( ){ char s1[5], s2[8], *p;p=s2;scanf("%s %s", s1, p );puts(s1); puts(p);}运行上述程序:qwe iop↙qweiop

Page 20: 第 8 章   指针

例 8-13 :改变数组指针的程序。

#include <stdio.h>main( ){ char *p = "money order";p = p+6;printf("%s \n", p);}

运行结果:order

Page 21: 第 8 章   指针

8.5 指针作为函数参数

例 8-15 :输入两个整数 a, b ,从大到小输出。main( ){ int a, b;

scanf("%d %d", &a, &b );if ( a < b ) swap (&a, &b );printf("%d %d \n", a, b );

}swap( int *q1, int *q2 ){ int tmp = *q1;

*q1 = *q2;*q2 = tmp;

}

Page 22: 第 8 章   指针

8.6 指向结构体的指针变量#include <stdio.h>struct student{ char xh[3], xm[7];

int cj;};main( ){ struct student *p, s;

p = &s; /* 将结构体变量 s 的起始地址存入指针 p 中 */scanf("%s%s%d", (*p).xh, (*p).xm, &s.cj );

/* 可通过指针 p 对 s 的域赋值 */printf("%s,%s,%d", p->xh, p->xm, p->cj );

/* 通过指针 p 输出 s 的内容 */}

运行:30 wang 79↙30, wang,79

以下 3 种形式等价: ① s.xh ② (*p).xh ③ p -> xh

Page 23: 第 8 章   指针

8.7 应用实例

• 例 8-20 :将数组 b 中 n 个整数按相反顺序存放。invert1 ( int b[ ], int n ) /* 用数组实现 */{ int tmp, i, j, m = n / 2;

i = 0; j = n -1;for ( ; i < m; i++, j-- ){ tmp = b[i];

b[i] = b[j];b[j] = tmp;

}}

invert2 ( int *p, int n ){int tmp, *i, *j;i = p;j = p + n - 1;for ( ; i < j; i++, j-- ){ tmp =*i;

*i =*j;*j =tmp;

}} /* 用指针实现 */

Page 24: 第 8 章   指针

本章小结

1 .指针 ( pointer ) 是用于存放内存地址的特殊变量 ( 这里地址一般是指内存中另一个变量的位置 ) 。称指针指向某个变量,也就是说,指针存放的是该变量的地址值。指针变量的命名规则同普通变量。

2 .通常所说的指针类型是指它所指向的变量的数据类型。3 .求地址运算符 & ,返回操作数变量在内存中的地址,而

与变量的内容无关。4 .运算符 * ,返回操作数所指变量的值。5 .下面三个表达式等价:

dd.year(*p).yearp->year