内容正文:
《C语言程序设计》
同步教学
(清华大学出版)
第九章 指 针
第9章 指 针(Pointer)
9.1 指针概述
9.2 指针与一维数组
9.3 指针与二维数组
9.4 指针与字符串
9.5 指针与函数
9.6 指针数组与多级指针
2
第九章 指 针
9.3 指针与二维数组
C语言将二维数组看作一维数组,其每个数组元素又是一个一维数组。二维数组:按行的顺序存放。
am-10 am-11 ……am-1n-1
a00 a01 …….. a0n-1
a10 a11 …….. a1n-1
………………….
a[m][n]=
am-1n-1
……..
am-11
am-10
……….
a1n-1
……..
a11
a10
a0n-1
…….
a01
a00
a[0]
a[1]
a[m-1]
单击此处编辑母版文本样式
第二级
第三级
第四级
第五级
3
第九章 指 针
9.3 指针与二维数组
int a[3][4]={
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
a 是一个数组名。
数组 a 包含3个元素:
a[0]、a[1]、a[2]。
每个元素又是一个一维数组,它包含4个元素。
a[0][0]
a[0][1]
a[0][2]
a[0][3]
a[1][0]
a[1][1]
a[1][2]
a[1][3]
a[2][0]
a[2][1]
a[2][2]
a[2][3]
元素
2000
2004
2008
2012
2016
2020
2024
2028
2032
2036
2040
2044
地址
第1行
第2行
第3行
a、a[0]
a[1]+1
a[0]+1
a+1、a[1]
a+2、a[2]
a[2]+1
单击此处编辑母版文本样式
第二级
第三级
第四级
第五级
4
一维数组a
a[1]
a[0][0] a[0][1] a[0][2] a[0][3]
a[1][0] a[1][1] a[1][2] a[1][3]
a[2][0] a[2][1] a[2][2] a[2][3]
行地址
列地址
列地址
列地址
a[0]+0 a[0]+1 a[0]+2 a[0]+3
a[2]+0 a[2]+1 a[2]+2 a[2]+3
a[1]+0 a[1]+1 a[1]+2 a[1]+3
一维数组a[2]
一维数组a[1]
一维数组a[0]
a[0]
a[2]
a+0
&a[0]
a+1
&a[1]
a+2
&a[2]
第九章 指 针
2. 再找到其所在的列
行确定后,只需进行行内再寻址,就可确定列地址。
第i 行第 j 列元素的地址为:a[i] + j *(a+i)+j
二维数组元素a[i][j]的定位: ( 指向数组元素的指针变量 )
1. 先找到其所在的行
由于二维数组按行存放,由二维数组的首地址 a,可以确定第 i 行的首地址为 a+i。
第 0 行首地址为: a 或 a+0 或 a[0]
第 i 行首地址为: a+i a[i] * (a+i)
第九章 指 针
所以,第 i 行第 j 列元素的值应为:
*( *(a+i)+j ) 或 *(a[i]+j) 或 a[i][j]
6
元素a[i][j]的地址的几种等价的引用方式
&a[i][j]
a[i]+j
*(a+i)+j
&(*(a+i))[j]
元素a[i][j]的几种等价的引用方式
a[i][j]
*(a[i]+j)
*(*(a+i)+j)
(*(a+i))[j]
第九章 指 针
7
行指针变量:
行指针变量 也称为指向一维数组的指针变量,一般定义形式为:
类型标识符 (*指针变量名) [常量表达式];
常量表达式: 表示一行含有多少个元素。在定义行指针变量时,必须确定每一行所含的元素个数。
int (*p)[4], (*q)[6], a[3][4], b[2][6];
p=a; /* p指向a的第l行的地址 */
q=b; /* q指向b的第l行的地址 */
p、q 虽然都是行指针变量,但类型不同。
p 指向的行只能有 4 个 int 型元素,
q 指向的行只能有 6 个 int 型元素。
第九章 指 针
8
【例9.6】输入一个3×4的矩阵到二维数组中,输出该矩阵,并且输出它的最大值元素及行列号。
#include <stdio.h>
void main()
{ int a[3][4], i, j, *maxp;
for(i=0;i<3;i++)
for(j=0;j<4;j++)
scanf("%d",*(a+i)+j);
for(i=0;i<3;i++)
{ for(j=0;j<4;j++)
printf("%3d",*(*(a+i)+j));
printf("
"); }
maxp=*a;
第九章 指 针
9.3 指针与二维数组
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
",*maxp, i+1, j+1);
}
9
【例9.7】输入一个4×4的矩阵到二维数组中,分别计算出二维数组中指定行,指定列的元素之和。
#include<stdio.h>
void main()
{ int a[4][4], (*p)[4] , s1, s2;
int i, j, n, m;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
scanf("%d", *(a+i)+j );
scanf("%d%d",&n,&m);
p=a+n-1; /* p 指向第n行 */
for(s1=0,j=0;j<4;j++)
s1 += *(*p+j);
第九章 指 针
9.3 指针与二维数组
p=a;
for(s2=0,i=0;i<4;i++)
s2 += *(*(p+i)+m-1);
/* *(*(p+i)+m-1)
即 a[i][m-1] */
printf("%d %d
",s1,s2);
}
10
字符串的首地址即为字符串指针。
对于一个字符串常量其值就是一个字符串指针,表示该字符串在内存中第一个字符的地址。
若字符数组中存放一个字符串,其数组名就是字符串指针,指向字符串的首字符。
第九章 指 针
9.4 指针与字符串
字符串的表示形式
(1) 字符串指针, 如:"abcd"
(2) 用字符数组存放字符串,如
char a[ ]= "Beijing China";
(3) 用字符指针变量指向字符串,
char *p= "a string"; 或
char *p; p= "a string";
(4) 字符串的引用
一般放在字符数组中或用指针变量指向一个字符串,引用时通过字符数组名或指向字符串的指针变量来引用字符串。
11
【例9.10】编写函数计算字符串的长度。
#include <stdio.h>
int length(char *s)
{ int k=0;
while(*s!='\0'){ k++; s++;} /* k表示字符个数 */
return k; }
void main()
{ char a[80]=
{"Beijing
China"};
printf("length: %d
",
length(a));
}
第九章 指 针
9.4 指针与字符串
12
一个函数在编译时被分配给一个入口地址。这个入口地址就称为函数的首地址
(函数指针)。
函数名代表函数的入口地址。
可以用函数名调用函数、也可以用指向函数的指针来调用函数。
第九章 指 针
9.5 指针与函数
1. 指向函数的指针
指向函数的指针变量的一般形式:
类型标识符 (*指针变量名)(函数形参类型)
类型标识符—表示指针变量所指向的函数的返回值类型;
函数形参类型—表示指针变量所指向的函数具有的参数类型。
char (*f1) (int);
int (*f2) (float, int);
13
第九章 指 针
9.5 指针与函数
2. 返回指针的函数
一个函数可以返回指针类型的数据,即地址值。
返回指针的函数的一般形式:
类型标识符 *函数名(类型标示符 形参,类型标示符 形参…)
其中“*”表示函数返回的值是指针。例如:
int *fun(float x, float y)
fun是函数名,调用它后能得到一个指向 int 型数据的指针(地址)。
14
第九章 指 针
9.6 指针数组与多级指针
1. 指针数组的定义
一个数组,其元素均为指针类型,则称为指针数组;
指针数组中的每一个元素都相当于一个指针变量;
指针数组常用于字符串数组的操作,省时间、省空间。
指针数组的一般形式:
类型标识符 *数组名[常量表达式];
int *p[10];
由于 [ ] 比 * 优先级高,所以 p 先与 [10] 结合,形成p[10],这是数组形式,它再与前面的 * 结合,表示此数组是指针类型的,每个数组元素都可指向一个 int 型变量。
15
第九章 指 针
9.6 指针数组与多级指针
1. 指针数组的定义
char *p[5]={"China", "Canada", "Singapore",
"Romania", "Mexico" };
16
第九章 指 针
9.6 指针数组与多级指针
2. 指针数组应用举例
char str[N][10] = { "Pascal", "Basic", "Fortran",
"Java", "Visual C " };
【例9.13】将若干字符串按字母顺序(由小到大)输出。
for (i=0; i<N-1; i++)
{
for (j = i+1; j<N; j++)
{
if (strcmp(str[j], str[i]) < 0)
{ strcpy(temp,str[i]);
strcpy(str[i],str[j]);
strcpy(str[j],temp);
}
}
}
17
第九章 指 针
9.6 指针数组与多级指针
【例9.13】将若干字符串按字母顺序(由小到大)输出。
str
str
str
str
str
str
str
str
str
str
方法1:二维数组方法
排序前
排序后
18
第九章 指 针
9.6 指针数组与多级指针
2. 指针数组应用举例
char *ptr[N] = { "Pascal", "Basic", "Fortran",
"Java", "Visual C " };
【例9.13】将若干字符串按字母顺序(由小到大)输出。
for (i=0; i<N-1; i++)
{
for (j = i+1; j<N; j++)
{
if (strcmp(ptr[j], ptr[i]) < 0)
{ temp = ptr[i];
ptr[i] = ptr[j];
ptr[j] = temp;
}
}
}
19
第九章 指 针
9.6 指针数组与多级指针
【例9.13】将若干字符串按字母顺序(由小到大)输出。
方法2:指针数组方法
指针数组ptr 字符串排序前
Pascal\0
Basic\0
Fortran\0
Java\0
Visual C\0
ptr[0]
ptr[1]
ptr[2]
ptr[3]
ptr[4]
指针数组ptr 字符串排序后
Pascal\0
Basic\0
Fortran\0
Java\0
Visual C\0
ptr[0]
ptr[1]
ptr[2]
ptr[3]
ptr[4]
20
第九章 指 针
9.6 指针数组与多级指针
3. 多级指针的概念
指向指针的指针称为二级指针,二级以上的指针称为多级指针。
多级指针定义的一般形式为:
类型标识符 ** … *指针变量名
指针变量名前有一个“*”,称为一级指针,简称指针。有两个星号“**”,则称为二级指针,依此类推。
int a=5;
int *b=&a; // 指针变量 b 中存放的是a 的地址
int **c=&b; // 二级指针c 中存放的是 b 的地址
21
谢谢观看
p[0]�
China�
p[1]�
Canada�
p[2]�
Singapore�
p[3]�
Romania�
p[4]�
Mexico�
���������
�������
name[0] P a s c a l \0 \0 \0 \0
name[1] B a s i c \0 \0 \0 \0 \0
name[2] F o r t r a n \0 \0 \0
name[3] J a v a \0 \0 \0 \0 \0 \0
name[4] V i s u a l C \0 \0
name[0] B a s i c \0 \0 \0 \0 \0
name[1] F o r t r a n \0 \0 \0
name[2] J a v a \0 \0 \0 \0 \0 \0
name[3] P a s c a l \0 \0 \0 \0
name[4] V i s u a l C \0 \0
$$