指 针 6.2 指针的概念 6.3 指针与数组 6.4 字符串的指针 6.5 指针数组和指向指针的指针,6.2.1 地址与指针的概念,6.2.2 指针的定义与引用,6.2 指针的概念,,指针的概念,指针是变量存放地址的变量 这个地址可以是变量的地址,也可以是复杂数据类型的地址,如数组,结构体等,也可以是函数的地址 指针变量存放了哪个变量的地址就称该指针指向了这个变量内存地址,1、变量与地址,程序中: int i; float k;,内存中每个字节有一个编号-----地址,i,k,编译或函数调用时为其分配内存单元,变量是对程序中数据 存储空间的抽象,2、数组与地址,地址,内存单元,整型数组元素a0,整型数组元素a1,整型数组元素a2,数组与地址对照表,程序中:int a3=1,2,3;,指针与指针变量,指针:一个变量的地址 指针变量:专门存放变量地址的变量叫,2000,指针,指针变量,变量的内容,变量的地址,,寻址,访问内存单元称为寻址 直接寻址:通过变量名对内存单元进行存取 间接寻址:通过指针变量间接存取指针变量的定义、初始化和引用,(一)、指针变量的定义和初始化,数据类型 *指针变量名1=初值1,;,指针变量的定义和初始化格式,例:指针变量的定义和初始化。
int a; int *p=,注意指针的指向 编译器不识别没有明确指向的指针但使用这样的指针可能导致错误二)、指针变量的引用方式,1、直接引用指针变量名,使用格式为:指针变量表达式 这个表达式必须是地址型表达式,例如:int i,*p_i, *q; p_i=,需要用到地址时,可以直接引用指针变量名例如:int i,j,*p=,2、通过指针变量来引用所指向的变量,使用格式为:* 指针变量名 在程序中“* 指针变量名”代表它所指向的变量例如:int i=1,j=2,k,*p=,(三)、取地址运算符与指针运算符,取地址运算符和指针运算符的运算对象、运算规则、结 合性如表所示 int *p; p= 这样指针p就指向了一维数组a,指向一维数组的指针变量的使用,处理数组元素的关键是引用数组元素,引用数组元素的方法与指针指向数组的方式有关:, 当指针变量指向数组首地址时,引用数组元素的方法如下:,引用“数组元素0” * (指针变量0) 或 * 指针变量 引用“数组元素i” * (指针变量i),1、用指针处理数组元素,这里的“指针变量1”代表同数组的下一个元素, 当指针变量指向下标为i的数组元素时,引用数组元素的方 法如下:,引用“数组元素i” * (指针变量0) 或 * 指针变量 引用“数组元素i-k” * (指针变量-k) 引用“数组元素i+k” * (指针变量k), 当指针变量指向首地址后,对下标为i的数组元素引用一共 有下列四种方法:,* (指针变量i) * (数组名i) 指针变量i 数组名i,方法1,2引用数组元素的方法使用了“指针运算符”,称为 “指针法”;方法3,4引用数组元素的方法使用了“下标运算符()” 称为“下标法”。
注意: 指针变量是存放地址这种数据类型的变量,可以按照变 量的处理方式对其进行运算;而数组名仅仅是一个地址常量, 只能按照常量的方式进行处理2、指向一维数组的指针变量的运算,当指针变量已指向数组后,对指针变量可以进行算术和 关系运算1)指针变量和整数的算术运算 对指针变量进行算术运算的规则如下:,指针变量整数 “指针变量中的地址整数*指针变量类型占 用单元数”对应的地址,指针变量整数 “指针变量中的地址整数*指针变量类型占 用单元数”对应的地址,指针变量 “指针变量中的地址指针变量类型占用单元 数”对应的地址,此后,指针变量将指向下一 个数组元素指针变量 “指针变量中的地址指针变量类型占用单元 数”对应的地址,此后,指针变量将指向上一 个数组元素指针变量 “指针变量中的地址”对应的地址(因为是后缀 减1运算符),此后,指针变量将指向上一个 数组元素指针变量 “指针变量中的地址”对应的地址(因为是后缀 增1运算符),此后,指针变量将指向下一个 数组元素。
上述运算规则组成的式子称为表达式,这种表达式的类 型是“地址型”,所以上述规则组成的表达式常称为“地址型表 达式”或“指针型表达式”,简称为“指针表达式”例如:设定义了整型数组a10,整型指针变量pa,且执行了 pa=a假定数组a的首地址为2000请看下列的表达式及其 运算结果:,执行papa5后 pa指向数组元素a5,pa的地址值将为 20005*22010,其中的“2”是整型数据 占用的单元数;,再执行pa后 pa将指向数组元素a4,pa的地址值将为 20101*22008注意:对代表地址常量的数组名不能进行增1减1的算术运算, ++a、a++、--a、a--、a=a+5、a=a-5都是错误的其中a为 数组名),(2)指针变量和指针变量的减法运算,指针变量和指针变量的减法运算规则如下: 指针变量1指针变量2,要求这两个指针变量必须指向同一个数组,否则不能进行 减法运算运算 结果为它们所指向的数组元素下标相差的整 数 例如,定义了数组a和同类型的指针变量p1、p2其中p1 指向数组元素a2;p2指向数组元素a6p1p2 结果为整数4 p2p1 结果为整数4,当两个指针变量的值(地址值)满足关系运算时,结果为1(真)否则结果为0(假)。
例如,定义了数组a和同类型的指针变量p1、p2;使p1指向数组元素a2;p2指向数组元素a3下列关系表达式及其运算结果:,p1
指向二维数组的指针变量的使用,1、指针变量指向二维数组的某个元素,当指针变量指向二维数组的某个元素时,利用指针变量 来处理该数组元素和处理一维数组元素的方法相同1)让指针变量指向二维数组的某个元素的方法 用初始化方式的格式为:类型 *指针变量 int i,j; for (i=0;i<2;i++) for (j=0;j<3;j++) p= ,程序如下:,2、指针变量指向二维数组的首地址,当指针变量指向二维数组的首地址时,也可以处理数组中 的任何一个元素1)让指针变量指向二维数组首地址的方法使用初始化或赋值方式都可以使指针变量指向二维数组的 首地址使用初始化方式有两种: 类型 * 指针变量二维数组名0 类型 * 指针变量 int i,j; for (i=0;i<2;i++) for (j=0;j<3;j++) scanf(“%d”,p+i*3+j); for (i=0;i<2;i++) printf(“n”); for (j=0;j<3;j++) printf(“%10d”,*(p+i*3+j)); ,3、指针变量指向二维数组中某个一维数组,(1)让指针变量指向二维数组中某个一维数组的方法。
如果你希望将指针变量指向二维数组中某个一维数组, 首先要按下列格式定义一个指针变量: 类型(* 指针变量)m 其中的m是对应二维数组的列长度,然后再用初始化或赋值方式将该指针变量指向二维数组的 首地址 类型(* 指针变量)m二维数组名 (初始化) 指针变量二维数组名 (赋值),二维数组中第i行对应的一维数组首地址可以用下列表达 式来获得: * (指针变量i),实际上等价于 指针变量i,使用这种指针变量,需要注意以下几点:, 定义这种指针变量时,圆括号不能丢 定义这种指针变量时,m必须是整型常量表达式,并且其值 要等于希望指向的一维数组的长度 定义这种指针变量后,赋初值或赋值时应该赋予列长度为m 的二维数组首地址,然后用表达式方式来获得二维数组中某 个一维数组的首地址2)二维数组元素的引用方法当某个指向一维数组的指针变量已指向对应二维数组的首 地址后,就可以用像处理一维数组元素的方式来处理这个二维 数组中已指向的一维数组具体的格式如下:,数组元素地址 *(指针变量行下标)列下标 数组元素引用 *(*(指针变量行下标)列下标),例如语句“int a25,(*p)5=a;”定义了二维数组a25和 指向具有5个元素的一维数组指针变量p,并且使p指向二维数 组a的首地址。
则对应二维数组中2个一维数组的首地址如下:,二维数组中的一维数组,用指针变量表示对应一维数组 的首地址,a0 a1,*(p0) *(p1),二维数组元素的引用格式如下:,数组元素 a00 a01 a02 a03 a04 引用格式 *(*(p+0)+0) *(*(p+0)+1) *(*(p+0)+2) *(*(p+0)+3) *(*(p+0)+4) 数组元素 a10 a11 a12 a13 a14 引用格式 *(*(p+1)+0) *(*(p+1)+1) *(*(p+1)+2) *(*(p+1)+3) *(*(p+1)+4),或者 p00 p01 p02 p03 p04,6.4 字符串的指针,字符串有: 常量字符串 例如:“ABC” 变量字符串 例如:char c“abc”;,无论哪一种字符串,都可以用字符型指针变指向它, 以后也可以用字符型指针来处理这个字符串或字符串中 的单个字符1、如何将指针变量指向字符串常量,第一种方法是给指针变量初始化的方式,格式为 char * 指针变量“字符串常量”;,假定要求字符型指针变量p指向字符串常量“abcd”;可以采 用下列两种方式:,第二种方法是先定义一个字符型指针变量,然后通过赋值 方式,其格式为“指针变量字符串常量”。
方法一 char *p=“abcd”; 方法二 char *p=NULL; p=“abcd”;,可以用赋值方式使指针变量指向字符串常量,但是不允 许将字符串常量赋值给字符型数组例如,下列的程序段是 错误的:,char a10; a=“abcd”;,C语言允许在同一个程序中,使同一个字符型指针变量先 后指向不同的字符串常量,例如下列的程序段是正确的:,char *pa=NULL; pa=“12345678”;, ,pa=“abcd”;,2. 指向存放字符串的字符数组的指针变量的使用,当一个字符型指针变量已指向某个字符串常量,就可以 利用指针变量来处理这个字符串处理的方式主要有两种:,(1)处理整个字符串 输出字符串 printf(“%s”,指针变量); 输入新的字符串代替原字符串 scanf(“%s”,指针变量);,(2)处理字符串中的单个字符 第i个字符的表示方法 * (指针变量i),6.5 指针数组和指向指针的指针,指针数组:若某个数组被定义为指针类型,则该数组为指针 数组 指针数组中的每个元素都相当于一个指针型变量,只能存放地址型数据 指向指针的指针:若定义的某个指针型变量专门用来存放其它指针变量的地址,则该指针变量为指针的指针,也叫二级指针。
1、指针数组的定义,需要注意指针数组是指针类型的,对其元素所赋的值必须 是地址值格式 存储类型 数据类型 * 指针数组名长度初值;,功能 定义指向“数据类型”变量或数组的指针型数组,同时给 指针数组元素赋初值这些指针变量具有指定的“存储 类型”说明 (1)指针数组名是标识符,前面必须有“*”号2)在一个定义语句中,可以同时定义普通变量、数组、指 针变量、指针数组可以给某些指针数组赋初值,而另 一些指针数组不赋初值3)定义指针变量时的“数据类型”可以选取任何基本数据类 型,也可以选取其它数据类型4)省略“存储类型”,默认为自动型(auto)5)其中的“初值”与普通数组赋初值的格式相同,每个初值 通常是“ int i; for (i=0;i<5;i++) pi=si; for (i=0;i<5;i++) scanf(“%s”,pi); for (i=0;i<5;i++) printf(“%sn”,pi); ,3、多级指针的定义和应用,在C语言中,把这种指针型变量称为“指针的指针”,意为 这种变量是指向指针变量的指针变量,也称多级指针通常使 用的多级指针是二级指针,相对来说,前面介绍的指针变量可 以称为“一级指针变量”。
二级指针变量的定义和赋初值方法如下:,格式 存储类型 数据类型 **指针变量名初值,,功能 定义指向“数据类型”指针变量的二级指针变量,同时给 二级指针变量赋初值说明,(1)二级指针变量名的构成原则是标识符,前面必须有“* *”号2)在一个定义语句中,可以同时定义普通变量、数组、指针 变量、指针数组、二级指针变量等可以给某些二级指针 变量赋初值,而另一些二级指针变量不赋初值3)定义时的“数据类型”可以选任何基本数据类型,也可以选 取以后介绍的其它数据类型这个数据类型是它将要指向 的指针变量所指向的变量或数组的数据类型4)其中的“初值”必须是某个一级指针变量的地址,通常是“ int i; for (i=0;i<5;i++) pi= ,,课堂练习指针应用程序设计例题,例1:输入n(不大于20)个单精度数存入一维数组,用指针变量 处理数组元素的方式将其逆序存放后输出n从键盘输入main() float a20,x,*pb,*pe; int n,k,i; scanf(“%d”, ,例2:求35整数矩阵中的最大元素、最小元素、所有元素的 平均值要求用指向二维数组首地址的指针变量按二维数组 排列方式处理二维数组元素。
程序清单如下:,main() int a35,*p=a,max,min,i,j; float ave=0.0; for (i=0;imax) max=*(p+i*5+j);,if (*(p+i*5+j)