1、第第 九九 章章指指 针针19.1 地址和指针的概念地址和指针的概念 指针是指针是C C语言的一个重要概念,语言的一个重要概念,也是也是C C语言的一个重要特色。深刻理语言的一个重要特色。深刻理解和正确使用指针是学习本章的基解和正确使用指针是学习本章的基本要求。本要求。本章是一个难点,也是一个重本章是一个难点,也是一个重点,初学者不易掌握。在理解和熟点,初学者不易掌握。在理解和熟悉基本内容的前提下,上机实验是悉基本内容的前提下,上机实验是必不可少的环节。必不可少的环节。29.1 地址和指针的概念地址和指针的概念正确灵活的运用指针正确灵活的运用指针 可以有效表示复杂的数据结构可以有效表示复杂的数
2、据结构 能动态分配内存能动态分配内存 方便使用字符串方便使用字符串 方便有效的使用数组方便有效的使用数组 调用函数时可以得到多个值调用函数时可以得到多个值 能直接处理内存地址能直接处理内存地址39.1 地址和指针的概念地址和指针的概念数据在内存中是如何存取的?数据在内存中是如何存取的?例:在程序中定义了一个变量,在编译时例:在程序中定义了一个变量,在编译时给这个变量分配内存单元,根据定义的变给这个变量分配内存单元,根据定义的变量类型,分配一定长度空间量类型,分配一定长度空间 内存中的每一个字节有一个编号,这就是内存中的每一个字节有一个编号,这就是地址,在地址所标志的内存单元中存放数地址,在地址
3、所标志的内存单元中存放数据据49.1 地址和指针的概念地址和指针的概念一、地址一、地址 在计算机中,把内存区划分为一个一个的存储单在计算机中,把内存区划分为一个一个的存储单元,每个单元为一个字节(位),它们都有一个编元,每个单元为一个字节(位),它们都有一个编号,这个编号就是内存地址。如下图所示:号,这个编号就是内存地址。如下图所示:注意:注意:1、程序中定义的每个数据、程序中定义的每个数据在编译后都占有各自的内存区。在编译后都占有各自的内存区。2、数据所占有的存储单元个数是、数据所占有的存储单元个数是由其类型决定的。由其类型决定的。3、首地址:第、首地址:第1个单元的地址个单元的地址4、表示
4、地址的数与整数的区别、表示地址的数与整数的区别59.1 地址和指针的概念地址和指针的概念二、举例二、举例 如有定义:如有定义:char c=A;int a=3;则所占内存情况如下:则所占内存情况如下:注意:注意:c和和a的的地址可能相邻,地址可能相邻,也可能不相邻,也可能不相邻,是由系统分配是由系统分配的,我们不用的,我们不用关心。关心。69.1地址和指针的概念地址和指针的概念三、直接访问和间接访问三、直接访问和间接访问 有两个上锁且放着物品的盒子有两个上锁且放着物品的盒子A、B,如果你有如果你有A盒子的钥匙,则可以直接打开盒子的钥匙,则可以直接打开A盒子盒子将物品取出;将物品取出;如果你有如
5、果你有B盒子的钥匙,而盒子的钥匙,而A盒子的钥匙在盒子的钥匙在B盒子盒子中,要想取出中,要想取出A盒子中的物品,则必须先打开盒子中的物品,则必须先打开B盒子,盒子,取出取出A盒子的钥匙,再打开盒子的钥匙,再打开A盒子将物品取出。盒子将物品取出。上面两种情况就是直接访问和间接访问的概念。上面两种情况就是直接访问和间接访问的概念。79.1地址和指针的概念地址和指针的概念1 1、直接访问、直接访问 通过变量本身对变量进行存取的方式,称为通过变量本身对变量进行存取的方式,称为直接访问。直接访问。如定义:如定义:int x;则则x=9;x+=5;等等等等 这种访问方式只需要变量本身就得到了该变这种访问方
6、式只需要变量本身就得到了该变量的全部信息,不需要其它内容,是直接的。量的全部信息,不需要其它内容,是直接的。其实程序在经过编译以后已经将变量名转换为变其实程序在经过编译以后已经将变量名转换为变量的地址,对变量值的存取都是通过地址进行的。量的地址,对变量值的存取都是通过地址进行的。89.1地址和指针的概念地址和指针的概念2 2、间接访问、间接访问 通过指针变量实现对变量的访问方式,称为间接通过指针变量实现对变量的访问方式,称为间接访问。访问。首先要定义一个指针变量,然后将一个同类型变首先要定义一个指针变量,然后将一个同类型变量的地址赋给该指针变量(这时我们称指针变量指向量的地址赋给该指针变量(这
7、时我们称指针变量指向该变量),这样就可以进行间接访问了。该变量),这样就可以进行间接访问了。间接访问的过程是:由指针变量得到变量的地址,间接访问的过程是:由指针变量得到变量的地址,根据该地址找到变量的存储区,再对该存储区的内容根据该地址找到变量的存储区,再对该存储区的内容进行存取,从而实现了对变量的间接访问。进行存取,从而实现了对变量的间接访问。99.1地址和指针的概念地址和指针的概念四、指针与指针变量四、指针与指针变量1、指针:简单地说,指针就是地址。二者是同、指针:简单地说,指针就是地址。二者是同一个概念的两种说法。只不过指针更形象一些,一个概念的两种说法。只不过指针更形象一些,就像一个针
8、一样,可以指向某个地方。就像一个针一样,可以指向某个地方。2、指针变量:专门存放变量地址的变量。首先、指针变量:专门存放变量地址的变量。首先指针变量就是一个变量,和我们以前所讲的其它指针变量就是一个变量,和我们以前所讲的其它变量没有本质区别。不同之处在于这种变量中所变量没有本质区别。不同之处在于这种变量中所存放的内容是地址。存放的内容是地址。109.1地址和指针的概念地址和指针的概念指针与指针变量关系指针与指针变量关系指针变量变量变量地址(指针)变量值指向地址存入指针变量11变量的指针就是变量的地址,存放变量地址变量的指针就是变量的地址,存放变量地址的变量是指针变量,用来指向另一个变量。的变量
9、是指针变量,用来指向另一个变量。为了表示指针变量和它所指向的变量之间的为了表示指针变量和它所指向的变量之间的关系,在程序中用关系,在程序中用*符号来表示符号来表示“指向指向”指针变量不同于其他类型的变量,它专门用指针变量不同于其他类型的变量,它专门用来存放地址,必须将它定义为来存放地址,必须将它定义为”指针类型指针类型“9.2 变量的指针和指向变量的指变量的指针和指向变量的指针变量针变量129.2 变量的指针和指向变量的变量的指针和指向变量的指针变量指针变量一、指针变量的定义和赋值一、指针变量的定义和赋值1、格式:类型名、格式:类型名 *指针变量名;指针变量名;2、举例、举例 int *p1;
10、char *s1,*s2;float *a1,*a2,*f;3、说明说明 a.类型名:指针变量所指向的变量类型。类型名:指针变量所指向的变量类型。b.*是定义指针变量的标志,不可丢掉。是定义指针变量的标志,不可丢掉。c.指针变量定义后,其值是不确定的,可以通过指针变量定义后,其值是不确定的,可以通过赋值语句使一个指针变量指向一个整型变量赋值语句使一个指针变量指向一个整型变量13为什么要指定类型名为什么要指定类型名 如果指针指向的是一个整型变量,那么指如果指针指向的是一个整型变量,那么指针加针加1就意味着地址值两个字节,如果是指就意味着地址值两个字节,如果是指向一个实型变量,则增加的应该是向一个
11、实型变量,则增加的应该是4个字节,个字节,所以一个指针变量只能指向同一个类型的所以一个指针变量只能指向同一个类型的变量变量149.2 变量的指针和指向变量的指变量的指针和指向变量的指针变量针变量4、赋值:可以进行初始化,也可以使用赋值语句、赋值:可以进行初始化,也可以使用赋值语句(1)、初始化:、初始化:int a,*s=&a;(2)、赋值语句、赋值语句 int a,*s;s=&a;(3)、注意:、注意:只能用同类型变量的地址进行赋值!只能用同类型变量的地址进行赋值!如如定义:定义:int *s;float f;则则 s=&f;是非法的。是非法的。15不定9.2 变量的指针和指向变量的指变量的
12、指针和指向变量的指针变量针变量在分析有关指针的程序时,画图是很好的方法:在分析有关指针的程序时,画图是很好的方法:sa若有:若有:int a=5,*s=&a;则则不定5&a169.2 变量的指针和指向变量的指变量的指针和指向变量的指针变量针变量二、指针变量的引用二、指针变量的引用1、两个运算符:、两个运算符:&与与*&:取地址运算符,注意与作位运算符时的不同:取地址运算符,注意与作位运算符时的不同(双目)(双目)*:取内容:取内容,指针运算符。注意与作乘运算符时,指针运算符。注意与作乘运算符时的不同(双目)的不同(双目)2、说明、说明 a.&既可作用于一般变量,也可作用于指针变量既可作用于一般
13、变量,也可作用于指针变量 b.*只能作用于指针变量只能作用于指针变量 c.定义指针变量时的定义指针变量时的*与该处的含义不同与该处的含义不同179.2 变量的指针和指向变量的指变量的指针和指向变量的指针变量针变量main()int a,b;int*pointer_1,*pointer_2;a=100;b=10;pointer_1=&a;pointer_2=&b;printf(%d,%dn,a,b);printf(%d,%dn,*pointer_1,*pointer_2);189.2 变量的指针和指向变量的指变量的指针和指向变量的指针变量针变量如果有pointer_1=&a;(1)&*point
14、er_1 结果是变量a的地址,*pointer_1相当于变量a(2)pointer_2=&*pointer_1;结果pointer_2指向变量a&和*两个运算符的优先级相同,按自右而左方向结合(3)*&a 等价于变量a(4)(*pointer_1)+相当于a+199.2 变量的指针和指向变量的指变量的指针和指向变量的指针变量针变量3、指针变量可以进行的操作、指针变量可以进行的操作(1)赋值:)赋值:int a,*p1=&a,*p2;p2=p1;(2)输出:输出:printf(“%x”,p1);(3)增减:增减:p1+;p2-;p1+=4;(4)取内容:)取内容:*p1=5;a=5;printf
15、(“%d”,*p1);(5)比较:与指针常量比较:与指针常量NULL进行比较,两指针变量进行比较,两指针变量 值的大小比较无意义。值的大小比较无意义。表示空指针,即不表示空指针,即不指向任何单元,在指向任何单元,在头文件头文件stdio.h中定中定义。义。define NULL 0209.2 变量的指针和指向变量的指变量的指针和指向变量的指针变量针变量例例9.1#include main()int a1=11,a2=22;int *p1,*p2;p1=&a1;p2=&a2;printf(“%d,%dn”,*p1,*p2);p2=p1;printf(“%d,%dn”,*p1,*p2);p1&a1
16、1122a1p2a2&a2*p1*p2&a1219.2 变量的指针和指向变量的指变量的指针和指向变量的指针变量针变量 例例9.2#include main()int a1=11,a2=22;int *p1,*p2,*p;p1=&a1;p2=&a2;printf(“%d,%dn”,*p1,*p2);p=p1;p1=p2;p2=p;printf(“%d,%dn”,*p1,*p2);p1&a11122a1p2a2&a2*p1*p2&a1&a2229.2 变量的指针和指向变量的指变量的指针和指向变量的指针变量针变量例例9.3#include main()int a1=11,a2=22,t;int *p
17、1,*p2;p1=&a1;p2=&a2;printf(“%d,%dn”,a1,a2);t=*p1;*p1=*p2;*p2=t;printf(“%d,%dn”,a1,a2);p1&a11122a1p2a2&a2*p1*p22211t 11239.2 变量的指针和指向变量的指变量的指针和指向变量的指针变量针变量例例9.4#include main()int a1=3;int *p1;p1=&a1;printf(“%xn”,p1);p1+;printf(“%xn”,p1);a10000001100000000ffccffcdffceffcfp1p1+249.2 变量的指针和指向变量的指变量的指针和指
18、向变量的指针变量针变量三、指针变量作为函数的参数三、指针变量作为函数的参数1、定义形式:只需要形式参数名前加上一个、定义形式:只需要形式参数名前加上一个*即可,即可,作用是将变量的地址传递到另一个函数中作用是将变量的地址传递到另一个函数中 如:如:void test(int *pointer,char f,char*s)2、说明、说明 参数的传递是值传递参数的传递是值传递,单向的(从实参到形参)。,单向的(从实参到形参)。那么如何理解通过指针作为参数可以改变主调函数中那么如何理解通过指针作为参数可以改变主调函数中变量的值呢?变量的值呢?形参得到实参的值形参得到实参的值(一个地址一个地址),函数
19、中可以通过形,函数中可以通过形参引用该地址,从而可以改变该地址对应变量的值。参引用该地址,从而可以改变该地址对应变量的值。但如果形参本身改变了,其值不会传给实参。但如果形参本身改变了,其值不会传给实参。259.2 变量的指针和指向变量的指变量的指针和指向变量的指针变量针变量main()int a,b;int*pointer_1,*pointer_2;scanf(%d,%d,&a,&b);pointer_1=&a;pointer_2=&b;if(ab)swap(pointer_1,pointer_2);printf(n%d,%dn,a,b);swap(int*p1,int*p2)int temp
20、;temp=*p1;*p1=*p2;*p2=temp;运行结果;5,99,526279.2 变量的指针和指向变量的指变量的指针和指向变量的指针变量针变量swap(int*p1,int*p2)int*temp;*temp=*p1;*p1=*p2;*p2=*temp;因为因为*temp所指向的单元是不可预见的,因此对所指向的单元是不可预见的,因此对*temp赋值可能会破坏系统的正常工作状况,应赋值可能会破坏系统的正常工作状况,应该将该将*p1的值赋给一个整型变量的值赋给一个整型变量28swap(int*p1,int*p2)int*p;p=p1;p1=p2;p2=p;main()int a,b;in
21、t*pointer_1,*pointer_2;scanf(%d,%d,&a,&b);pointer_1=&a;pointer_2=&b;if(ab)swap(pointer_1,pointer_2);printf(n%d,%dn,*pointer_1,*pointer_2);29309.3 指针与数组指针与数组 在在语言中,指针与数组有着密语言中,指针与数组有着密切的关系。对数组元素,既可以采用切的关系。对数组元素,既可以采用数组下标来引用,也可以通过指向数数组下标来引用,也可以通过指向数组元素的指针来引用。采用指针方法组元素的指针来引用。采用指针方法处理数组,可以产生代码长度小、运处理数组,
22、可以产生代码长度小、运行速度快的程序。行速度快的程序。319.3 指针与数组指针与数组一、指向数组元素的指针一、指向数组元素的指针设有数组定义为:设有数组定义为:int a5;则有:则有:(1)a表示数组在内存中的首地址表示数组在内存中的首地址,也就是数组中第,也就是数组中第1 个元素的首地址,它是一个地址常量,其值由系个元素的首地址,它是一个地址常量,其值由系 统在编译时确定,程序运行期间不能改变。统在编译时确定,程序运行期间不能改变。(2)数组中的各元素表示为:数组中的各元素表示为:a0、a1、a2、a3、a4数组的指针是数组的起始地址数组的指针是数组的起始地址 a数组元素的指针是数组元数
23、的地址数组元素的指针是数组元数的地址&a0、&a332int a10;int*p;下面两个语句等价:p=&a0;p=a;在定义的时候也可以赋初值int*p=&a0;339.3 指针与数组指针与数组二、通过指针引用数组元素二、通过指针引用数组元素(1)数组中的各元素的地址数组中的各元素的地址表示为:表示为:&a0、&a1、&a2、&a3、&a4 或者是:或者是:a+0(或(或a)、)、a+1、a+2、a+3、a+4(2)数组元数又可表示成:数组元数又可表示成:*(a+0)(或或*a)、)、*(a+1)、*(a+2)、*(a+3)、*(a+4)(3)数组的逻辑结构如下:数组的逻辑结构如下:a0a1
24、a2a3a4a&a0&a1&a2&a3&a4349.3 指针与数组指针与数组现定义一个指针变量:现定义一个指针变量:int *s;并进行赋值:并进行赋值:s=a;或或 s=&a0;则,指针变量则,指针变量s指向了数组指向了数组a的开始,二者产生了联的开始,二者产生了联系,这样就可以通过指针变量系,这样就可以通过指针变量s访问数组访问数组a了。了。a0a1a2a3a4a&a0&a1&a2&a3&a4s注意:注意:a是指针常量,是指针常量,s是指针变量。是指针变量。359.3 指针与数组指针与数组当然,对当然,对s也可以进行其它赋值,如:也可以进行其它赋值,如:s=a+2;或或 s=&a2;图变为
25、:图变为:a0a1a2a3a4a&a0&a1&a2&a3&a4s说明:若进行操作说明:若进行操作 s=a;s+=2;效果与上述相同。效果与上述相同。36说明:说明:p+i和和a+i就是就是ai的地址,他们都是指向的地址,他们都是指向a数数组的第组的第i+1个元素个元素*(p+i)或或*(a+i)是是p+i或或a+i所指向的数组元素所指向的数组元素指向数组的指针变量也可以带下标如:指向数组的指针变量也可以带下标如:pi和和*(p+i)是等价的是等价的379.3 指针与数组指针与数组当一个指针变量指向数组的首地址后,关系图为:当一个指针变量指向数组的首地址后,关系图为:数组数组int a5指向数组
26、元素的指针指向数组元素的指针int*s指向数组元素的访问指向数组元素的访问a,&a0,s,&s0a+1,&a1,s+1,&s1a+i,&ai,s+i,&sia0,*a,s0,*sa1,*(a+1),s1,*(s+1)ai,*(a+i),si,*(s+i)389.3 指针与数组指针与数组总结:一维数组的访问总结:一维数组的访问例例 用多种方法访问一维数组各元素用多种方法访问一维数组各元素#include main()int a5=1,3,5,7,9,i,*p=a;for(i=0;i5;i+)printf(“%d”,ai);for(i=0;i5;i+)printf(“%d”,*(a+i);for(
27、i=0;i5;i+)printf(“%d”,pi);for(i=0;i5;i+)printf(“%d”,*(p+i);for(;pa+5;p+)printf(“%d”,*p);p=a;while(pp*(+p)使使p加加1,再取,再取*p(*p)+表示表示p所指向的元素加所指向的元素加1。是元素值加。是元素值加1,不是,不是指针值加指针值加1419.3 指针与数组指针与数组三、用数组名作函数参数三、用数组名作函数参数1、函数的定义形式、函数的定义形式例如:例如:int func(int array,int n)函数体;函数体;也可以写为:也可以写为:int func(int *pointer,
28、int n)函数体;函数体;429.3 指针与数组指针与数组2、函数的说明形式、函数的说明形式如有函数定义:如有函数定义:int func(int array,int n)函数体;函数体;则对该函数的说明形式可以写为:则对该函数的说明形式可以写为:int func(int array,int n);int func(int *array,int n);439.3 指针与数组指针与数组例例 编写在数组的最后一个元素中存放其它元素编写在数组的最后一个元素中存放其它元素 和的函数和的函数#include void summary(int *p,int n);main()static int a11=
29、1,2,3,4,5,6,7,8,9,9;summary(a,9);printf(“Sum is%dn”,a9);void summary(int *p,int n)int s=0;while(n)s+=*(p+);*p=s;函数还可写为:函数还可写为:void summary(int arr,int n)int i,s=0;for(i=0;in;i+)s+=arri;arrn=s;44例:将数组中n个整数按相反的顺序存放45main()int i,a10=3,7,9,11,0,6,7,5,4,2;printf(“The original array:n”);for(i=0;i10;i+)pri
30、ntf(“%d,”,ai);printf(“n”);inv(a,10);printf(“The array has been inverted:n”);for(i=0;i10;i+)printf(“%d,”,ai);printf(“n”);46void inv(int x,int n)/*形参形参x为数组名为数组名*/int temp,i,j,m=(n-1)/2;for(i=0;i=m;i+)j=n-1-i;temp=xi;xi=xj;xj=temp;3791106754224576011973mij47void inv(int*x,int n)/*形参形参x为指针变量为指针变量*/int*p
31、,temp,*i,*j,m=(n-1)/2;i=x;j=x+n-1;p=x+m;for(;i=p;i+,j-)temp=*i;*i=*j;*j=temp;37911067542i,xp=x+mj48 例:从例:从10个数中找出其中的最大值和最个数中找出其中的最大值和最小值小值 不要求改变数组元素的值,只是找到最大不要求改变数组元素的值,只是找到最大和最小值,为了能得到两个结果,我们用和最小值,为了能得到两个结果,我们用两个全局变量在函数间传递数据两个全局变量在函数间传递数据49int max,min;main()void max_min_value(int array,int n);int i
32、,number10;printf(enter 10 integer number:n);for(i=0;i10;i+)scanf(%d,&numberi);max_min_value(number,10);printf(nmax=%d,min=%dn,max,min);getch();50void max_min_value(int array,int n)int*p,*array_end;array_end=array+n;max=min=*array;for(p=array+1;pmax)max=*p;else if(*pmin)min=*p;相当于*(array+0)或array0arr
33、ayp(开始)array_end51 函数函数max_min_value的形参的形参array可以改可以改为指针变量类型;为指针变量类型;void max_min_value(int*array,int n)实参也可以不用数组名,而用指针变量实参也可以不用数组名,而用指针变量传递地址,形参仍用指针变量传递地址,形参仍用指针变量52int max,min;void max_min_value(int*array,int n)int*p,*array_end;array_end=array+n;max=min=*array;for(p=array+1;pmax)max=*p;else if(*pm
34、in)min=*p;形参为指针变量类型53main()int i,number10,*p;p=number;printf(enter 10 integer numbers:n);for(i=0;i10;i+,p+)scanf(%d,p);printf(the 10 integer numbers:n);for(p=number,i=0;i10;i+,p+)printf(%d,*p);p=number;max_min_value(p,10);printf(nmax=%d,min=%dn,max,min);getch();实参为指针变量类型54总结:若一个实参数组,想在函数中改变此数若一个实参数组
35、,想在函数中改变此数组元素的值,实参和形参的表示形式有组元素的值,实参和形参的表示形式有以下以下4种情况:种情况:55第一种情况:形参和实参都用数组名:形参和实参都用数组名:形参和实参数组共用同一段内存单元形参和实参数组共用同一段内存单元main()int a10;f(a,10);f(int x,int n)56第二种情况:实参用数组名,形参用指针变量实参用数组名,形参用指针变量 通过形参的变化就可以指向实参数组的任通过形参的变化就可以指向实参数组的任何一个元素何一个元素main()int a10;f(a,10);f(int*x,int n)57第三种情况:实参形参都用指针变量实参形参都用指针
36、变量 传递指针变量的值,其实就是数组的首地传递指针变量的值,其实就是数组的首地址,通过形参指针的变化指向数组的任一址,通过形参指针的变化指向数组的任一元素,从而改变数组的值元素,从而改变数组的值main()int a10,*p;p=a;f(p,10);f(int*x,int n)58第四种情况:实参为指针变量,形参为数组名实参为指针变量,形参为数组名 将数组的首地址传给形参指针,形参指针将数组的首地址传给形参指针,形参指针指向数组的首元素指向数组的首元素main()int a10,*p;p=a;f(p,10);f(int x,int n)59 以上的四种方法,实质上都是地址的传以上的四种方法,
37、实质上都是地址的传递,递,1和和4只是形式上的不同,实质上都只是形式上的不同,实质上都是使用的指针变量是使用的指针变量注意:如果使用指针变量作实参,必须注意:如果使用指针变量作实参,必须先使指针变量有确定值,指向一个已定先使指针变量有确定值,指向一个已定义的数组!如果不设数组,只设指针变义的数组!如果不设数组,只设指针变量,就会出错。量,就会出错。60选择法排序:main()int*p,i,a10;p=a;for(i=0;i10;i+)scanf(%d,p+);p=a;sort(p,10);for(p=a,i=0;i10;i+)printf(%d,*p);p+;getch();61sort(i
38、nt x,int n)int i,j,k,t;for(i=0;in-1;i+)k=i;for(j=i+1;jxk)k=j;if(k!=i)t=xi;xi=xk;xk=t;用数组名作为形参,用下标法引用新参数组元素,62sort(int*x,int n)int i,j,k,t;for(i=0;in-1;i+)k=i;for(j=i+1;j*(x+k)k=j;if(k!=i)t=*(x+i);*(x+i)=*(x+k);*(x+k)=t;形参是指针变量63指向二维数组的指针和指针变量指向二维数组的指针和指针变量一、多维数组的地址 int a34=1,3,5,7,9,11,13,15,17,19,2
39、1,23;a是一个数组名,a数组名包含3行,即三个元素:a0,a1,a2.而每一个元素又是一个一维数组 a0:a00 a01 a02 a1:a10 a11 a12 a2:a20 a21 a2264指向二维数组的指针和指针变量指向二维数组的指针和指针变量从二维数组的角度来看,a代表整个二维数组的地址,也就是0行的首地址,a1代表第1行的首地址,也就是a1的地址a0代表第0行一维数组第0列元素的地址,即&a00,a1的值是&a10a2的值是&a2065指向二维数组的指针和指针变量指向二维数组的指针和指针变量第0行第1列的元素的地址可以用a0+1来表示,这里的1代表1个列元素的字节数,即两个字节。即
40、&a0166表示形式表示形式含义含义地址值地址值&a指向二维数组的指针指向二维数组的指针2000a 二维数组名,指向二维数组名,指向a0,第第0行首地址行首地址2000a0,*(a+0),*aa00的地址的地址2000a+1,&a1第第1行首地址行首地址2008a1,*(a+1)第第1行第行第0列元素地址列元素地址2008a1+2,*(a+1)+2,&a12 第第1行第行第2列元素的地址列元素的地址2012*(a1+2),*(*(a+1)+2),a12第第1行第行第2列元素的值列元素的值元素值元素值1367指向二维数组的指针和指针变量指向二维数组的指针和指针变量二、指向多维数组的指针变量(1)
41、指向数组元素的指针变量main()int a34=1,3,5,7,9,11,13,15,17,19,21,23;int*p;for(p=a0;pa0+12;p+)if(p-a0)%4=0)printf(“n”);printf(“%4d”,*p);68指向二维数组的指针和指针变量指向二维数组的指针和指针变量要输出某个指定的数组元素,a12,则应事先计算该元素在数组中的相对位置,计算aij在数组中的相对位置的计算公式:i*m+j(其中m为二维数组的列数)如果数组下标从1开始的话那么计算机公式就改为:(i-1)*m+(j-1)69指向二维数组的指针和指针变量指向二维数组的指针和指针变量(2)指向由m
42、个元素组成的一维数组的指针变量 p指向一个包含m个元素的一维数组,如果p先指向a0即p=&a0,则p+1不是指向a01,而是指向a1,p的增值以一维数组的长度为单位70指向二维数组的指针和指针变量指向二维数组的指针和指针变量main()int a34=1,3,5,7,9,11,13,15,17,19,21,23;int(*p)4,i,j;p=a;scanf(“i=%d,j=%d”,&i,&j);printf(“a%d,%d=%dn”,i,j,*(*(p+i)+j);719.4 指针与字符串指针与字符串 字符串是一种特殊的一维数组,字符串是一种特殊的一维数组,所以上节中介绍的方法同样适用于对所以
43、上节中介绍的方法同样适用于对字符串的访问。字符串的访问。字符串的特殊性在于:字符串的特殊性在于:字符串的字符串的末尾是结束标志末尾是结束标志 0 0,所以访问字,所以访问字符串时常用结束标志进行判断。符串时常用结束标志进行判断。729.4 指针与字符串指针与字符串一、字符串指针作函数参数一、字符串指针作函数参数1、字符串结构的分析、字符串结构的分析设有数组定义为:设有数组定义为:char s=“abcde”;则则s是一个是一个字符数组,它里面存放的是一个字符串。它在内存字符数组,它里面存放的是一个字符串。它在内存中占用中占用6个字节,但长度为个字节,但长度为5。其结构为:。其结构为:a b c
44、 d e 0s s0 s1 s2 s3 s4 s5结束标志结束标志739.4 指针与字符串指针与字符串字符串还可以定义为:字符串还可以定义为:char *s=“abcde”;它在内它在内存中占用存中占用6个字节,长度为个字节,长度为5。其结构为:。其结构为:a b c d e 0s s0 s1 s2 s3 s4 s5结束标志结束标志74说明程序在定义字符指针变量的时候,是把程序在定义字符指针变量的时候,是把字符串的首地址(即存放字符串的字符字符串的首地址(即存放字符串的字符数组的首地址)赋给数组的首地址)赋给ss作为一个指针变量,指向字符型数据,作为一个指针变量,指向字符型数据,只能指向一个字
45、符变量或其他字符类型只能指向一个字符变量或其他字符类型数据,不能同时指向多个字符数据数据,不能同时指向多个字符数据75说明char*string;*string=“abc”;就是错误的,但可以 string=“abc”;也可以 char *string=“abc”;输出时:printf(“%sn”,string);字符指针变量名string,则系统先输出它所指向的一个字符数据,然后自动使string加1,使之指向下一个字符,然后再输出一个字符如此直到遇到字符串结束标志n为止对于字符串种字符的存取,可以用下标方法,也可以用指针方法76例:例:例例 将字符数组将字符数组a中的字符串拷贝到字符数组中
46、的字符串拷贝到字符数组b中中(1)下标法下标法 (2)指针法指针法#include#include main()main()char a=“Hello,world!”,b20;char a=“Hello,world!”,b20;int i;char*pa,*pb;for(i=0;ai!=0;i+)for(pa=a,pb=b;*pa!=0;pa+,pb+)bi=ai;*(b+i)=*(a+i);*pb=*pa;bi=0;*(b+i)=0;*pb=0;printf(“%sn”,b);printf(“%sn”,b);779.4 指针与字符串指针与字符串二、字符串指针作函数参数二、字符串指针作函数参数
47、1、函数的定义形式、函数的定义形式例如:例如:char func(char a,char b)函数体;函数体;也可以写为:也可以写为:char func(char *a,char *b)函数体;函数体;78例:例:设计一函数,实现与标准函数设计一函数,实现与标准函数strcpy类似的功能。类似的功能。#include void mystrcpy(char *to,char *from);main()char ca20,*cp=“Hello,world!”;mystrcpy(ca,cp);printf(“%s”,ca);void mystrcpy(char *to,char *from)whil
48、e (*from!=0)*to=*from;to+;from+;*to=0;79while(*from!=0)*to=*from;to+;from+;while(*to=*from)!=0)to+;from+while(*to+=*from+)!=0)while(*from!=0)*to+=*from+;while(*from)*to+=*from+;while(*to+=*from+)for(;(*to+=*from+)!=0;)80也可以用指针变量(局部变量)void copy_string(char from,char to)char*p1,*p2;p1=from;p2=to;while
49、(*p2+=*p1+)!=0);81总结:实参实参形参形参数组名数组名数组名数组名数组名数组名字符指针变量字符指针变量字符指针变量字符指针变量字符指针变量字符指针变量字符指针变量字符指针变量数组名数组名829.4 字符指针变量和字符数组字符指针变量和字符数组字符数组由若干个元素组成,每个元素种放一个字符,而字符指针变量中存放的是地址(字符串的首地址),决不是将字符串放到字符指针变量中83赋值方式对字符数组只能对各个元素赋值 如:char str14;string=“I love China!”;是错误的而对字符指针变量,可以采用以下方法 如:char*a;a=“I love China!”;8
50、4对字符指针变量赋初值 char*a=“I love China!”;等价于:等价于:char*a;a=“I love China!”;对数组的初始化对数组的初始化 char str14=“I love China!”;不能等价于:不能等价于:char str14;str=“I love China!”;即数组可以在定义时整体赋初值,但不能在赋值即数组可以在定义时整体赋初值,但不能在赋值语句中整体赋值语句中整体赋值85定义的字符数组,在编译时为它分配内存单元,它有确定的地址。定义指针变量时,给指针变量分配内存单元,放一个地址值,该指针变量就指向一个字符型数据,char str10;scanf(
侵权处理QQ:3464097650--上传资料QQ:3464097650
【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。