240 likes | 357 Views
第 8 章 指针. 8.1 指针的概念 8.2 指向简单变量的指针 8.3 指向数组的指针变量 8.4 指向字符串的指针变量 8.5 指针作为函数参数 8.6 指向结构体的指针变量 8.7 应用实例 本章小结. 8.1 指针的概念. 指针,也就是内存地址。 指针变量是用来存放这些内存地址的变量。 不同类型指针变量所占用的存储单元长度是相同的 . 直接访问方式 : 根据变量名实现对存储空间的访问。 间接访问方式 : 通过存放地址的 指针 变量实现对存储空间的访问。.
E N D
8.1 指针的概念 8.2 指向简单变量的指针 8.3 指向数组的指针变量 8.4 指向字符串的指针变量 8.5 指针作为函数参数 8.6 指向结构体的指针变量 8.7 应用实例 本章小结
8.1 指针的概念 • 指针,也就是内存地址。 • 指针变量是用来存放这些内存地址的变量。 • 不同类型指针变量所占用的存储单元长度是相同的. • 直接访问方式:根据变量名实现对存储空间的访问。 • 间接访问方式:通过存放地址的指针变量实现对存储空间的访问。
如果将变量x的地址2060存放到另一个变量p中,即p的值为2060,这样通过变量p可以找到变量x的地址,从而找到 x 的值。存放地址的变量p就是指针变量。可以形象地说,p指向x。
"*" 是指针运算符,或称为“间接访问”运算符。*p表示指针变量p所指向的变量。若要改变x变量的值,也可通过改变 *p的值来实现。如执行 *p = 47;则此时x=47。 • "&" 也是一个指针运算符,称为取地址运算符。如为了让指针p指向变量x,可执行p = &x,此时变量x的地址即存入了指针p中。 • 注意,指针变量只能存放地址值,不要将一个整型数据赋给一个指针变量。
8.2 指向简单变量的指针 • 指针变量也必须先定义后使用。 • 格式如下: 类型标识符 * 指针变量名; 例如: int *p1, p2; 则p1是指针变量,而p2是整型变量。
例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 ); }
8.3 指向数组的指针变量 • 任何可通过数组下标完成的操作也可通过指针完成。 • 然而它们之间也存在细微但很重要的区别。一般来讲,使用指针速度更快,程序更紧凑。
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],每个元素都指向整型变量。
如果数组为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) 都是等价的。
例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, 5 4, 4, 4 3, 3, 3 2, 2, 2 1, 1, 1
例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 说明:指针变量和数组名有区别,指针变量是一个变量,可以改变其值,而数组名是数组首地址,是一个地址常量,不能对它赋值。
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个元素的一维数组。
例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
例8-8:用指针输出二维数组的各元素。 #include <stdio.h> #define M 4 #define N 3 #define L M*N main ( ) { 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" ); /* 换行 */ } }
8.4 指向字符串的指针变量 • 在C语言中,字符串可以用字符数组实现。其实,字符串还可以用字符指针实现,而且字符指针更方便、简洁。 • 例如: char string[ ] = "this is a string!"; char *pstr = "that is a book!";
例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; /* 补上串结尾符 */ }
用指针方法 void strcpy ( char *p,char *q ) { while ( *q != '\0' ) { *p = *q; p++; q++; } *p=0; /* 补上串结尾符 */ }
例8-12:分别用字符指针和字符数组表示字符串。例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↙ qwe iop
例8-13:改变数组指针的程序。 #include <stdio.h> main( ) { char *p = "money order"; p = p+6; printf("%s \n", p); } 运行结果: order
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; }
8.6 指向结构体的指针变量 以下3 种形式等价: ① s.xh ② (*p).xh ③ p -> xh #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
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; } } /*用指针实现*/
本章小结 1.指针( pointer )是用于存放内存地址的特殊变量( 这里地址一般是指内存中另一个变量的位置 )。称指针指向某个变量,也就是说,指针存放的是该变量的地址值。指针变量的命名规则同普通变量。 2.通常所说的指针类型是指它所指向的变量的数据类型。 3.求地址运算符&,返回操作数变量在内存中的地址,而与变量的内容无关。 4.运算符*,返回操作数所指变量的值。 5.下面三个表达式等价: dd.year (*p).year p->year