1、让让你你不不再再害害怕怕指指针针前前言言:复复杂杂类类型型说说明明要要了了解解指指针针,多多多多少少少少会会出出现现一一些些比比较较复复杂杂的的类类型型,所所以以我我先先介介绍绍一一下下如如何何完完全全理理解解一一个个复复杂杂类类型型,要要理理解解复复杂杂类类型型其其实实很很简简单单,一一个个类类型型里里会会出出现现很很多多运运算算符符,他他们们也也像像普普通通的的表表达达式式一一样样,有有优优先先级级,其其优优先先级级和和运运算算优优先先级级一一样样,所所以以我我总总结结了了一一下下其其原原则则:从从变变量量名名处处起起,根根据据运运算算符符优优先先级级结结合合,一一步步一一步步分分析析.下
2、下面面让让我我们们先先从从简简单单的的类类型型开开始始慢慢慢慢分分析析吧吧:int p;int p;/这这是是一一个个普普通通的的整整型型变变量量int*p;int*p;/首首先先从从 P P 处处开开始始,先先与与*结结合合,所所以以说说明明 P P 是是一一/个个指指针针,然然后后再再与与 intint 结结合合,说说明明指指针针所所指指向向/的的内内容容的的类类型型为为 intint 型型.所所以以 P P 是是一一个个返返回回整整/型型数数据据的的指指针针int p3;int p3;/首首先先从从 P P 处处开开始始,先先与与结结合合,说说明明 P P 是是一一个个数数/组组,然然后
3、后与与 intint 结结合合,说说明明数数组组里里的的元元素素是是整整/型型的的,所所以以 P P 是是一一个个由由整整型型数数据据组组成成的的数数组组int*p3;int*p3;/首首先先从从 P P 处处开开始始,先先与与结结合合,因因为为其其优优先先级级/比比*高高,所所以以 P P 是是一一个个数数组组,然然后后再再与与*结结合合,说说明明/数数组组里里的的元元素素是是指指针针类类型型,然然后后再再与与 intint 结结合合,/说说明明指指针针所所指指向向的的内内容容的的类类型型是是整整型型的的,所所以以/P/P 是是一一个个由由返返回回整整型型数数据据的的指指针针所所组组成成的的
4、数数组组int(*p)3;int(*p)3;/首首先先从从 P P 处处开开始始,先先与与*结结合合,说说明明 P P 是是一一个个指指针针/然然后后再再与与结结合合(与与()()这这步步可可以以忽忽略略,只只是是为为/了了改改变变优优先先级级),),说说明明指指针针所所指指向向的的内内容容是是一一个个/数数组组,然然后后再再与与 intint 结结合合,说说明明数数组组里里的的元元素素是是/整整型型的的.所所以以 P P 是是一一个个指指向向由由整整型型数数据据组组成成的的数数/组组的的指指针针int*p;int*p;/首首先先从从 P P 开开始始,先先与与*结结合合,说说是是 P P 是
5、是一一个个指指针针,然然/后后再再与与*结结合合,说说明明指指针针所所指指向向的的元元素素是是指指针针,然然/后后再再与与 intint 结结合合,说说明明该该指指针针所所指指向向的的元元素素是是整整/型型数数据据.由由于于二二级级指指针针以以及及更更高高级级的的指指针针极极少少用用/在在复复杂杂的的类类型型中中,所所以以后后面面更更复复杂杂的的类类型型我我们们就就/不不考考虑虑多多级级指指针针了了,最最多多只只考考虑虑一一级级指指针针.int p(int);int p(int);/从从 P P 处处起起,先先与与()()结结合合,说说明明 P P 是是一一个个函函数数,然然后后进进入入/()
6、/()里里分分析析,说说明明该该函函数数有有一一个个整整型型变变量量的的参参数数/然然后后再再与与外外面面的的 intint 结结合合,说说明明函函数数的的返返回回值值是是/一一个个整整型型数数据据I Int(*p)(int);nt(*p)(int);/从从 P P 处处开开始始,先先与与指指针针结结合合,说说明明 P P 是是一一个个指指针针,然然后后与与/()/()结结合合,说说明明指指针针指指向向的的是是一一个个函函数数,然然后后再再与与()()里里的的/int/int 结结合合,说说明明函函数数有有一一个个 intint 型型的的参参数数,再再与与最最外外层层的的/int/int 结结
7、合合,说说明明函函数数的的返返回回类类型型是是整整型型,所所以以 P P 是是一一个个指指/向向有有一一个个整整型型参参数数且且返返回回类类型型为为整整型型的的函函数数的的指指针针int*(*p(int)3;int*(*p(int)3;/可可以以先先跳跳过过,不不看看这这个个类类型型,过过于于复复杂杂/从从 P P 开开始始,先先与与()()结结合合,说说明明 P P 是是一一个个函函数数,然然后后进进/入入()()里里面面,与与 intint 结结合合,说说明明函函数数有有一一个个整整型型变变量量/参参数数,然然后后再再与与外外面面的的*结结合合,说说明明函函数数返返回回的的是是/一一个个指
8、指针针,然然后后到到最最外外面面一一层层,先先与与结结合合,说说明明/返返回回的的指指针针指指向向的的是是一一个个数数组组,然然后后再再与与*结结合合,说说/明明数数组组里里的的元元素素是是指指针针,然然后后再再与与 intint 结结合合,说说明明指指/针针指指向向的的内内容容是是整整型型数数据据.所所以以 P P 是是一一个个参参数数为为一一个个/整整数数据据且且返返回回一一个个指指向向由由整整型型指指针针变变量量组组成成的的数数组组/的的指指针针变变量量的的函函数数.说说到到这这里里也也就就差差不不多多了了,我我们们的的任任务务也也就就这这么么多多,理理解解了了这这几几个个类类型型,其其
9、它它的的类类型型对对我我们们来来说说也也是是小小菜菜了了,不不过过我我们们一一般般不不会会用用太太复复杂杂的的类类型型,那那样样会会大大大大减减小小程程序序的的可可读读性性,请请慎慎用用,这这上上面面的的几几种种类类型型已已经经足足够够我我们们用用了了.1 1、细细说说指指针针指指针针是是一一个个特特殊殊的的变变量量,它它里里面面存存储储的的数数值值被被解解释释成成为为内内存存里里的的一一个个地地址址。要要搞搞清清一一个个指指针针需需要要搞搞清清指指针针的的四四方方面面的的内内容容:指指针针的的类类型型、指指针针所所指指向向的的类类型型、指指针针的的值值或或者者叫叫指指针针所所指指向向的的内内
10、存存区区、指指针针本本身身所所占占据据的的内内存存区区。让让我我们们分分别别说说明明。先先声声明明几几个个指指针针放放着着做做例例子子:例例一一:(1)int*ptr;(1)int*ptr;(2)char*ptr;(2)char*ptr;(3)int*ptr;(3)int*ptr;(4)int(*ptr)3(4)int(*ptr)3;(5)int*(*ptr)4;(5)int*(*ptr)4;1.1.指指针针的的类类型型从从语语法法的的角角度度看看,你你只只要要把把指指针针声声明明语语句句里里的的指指针针名名字字去去掉掉,剩剩下下的的部部分分就就是是这这个个指指针针的的类类型型。这这是是指指针
11、针本本身身所所具具有有的的类类型型。让让我我们们看看看看例例一一中中各各个个指指针针的的类类型型:(1)int*ptr;/(1)int*ptr;/指指针针的的类类型型是是 int*int*(2)char*ptr;/(2)char*ptr;/指指针针的的类类型型是是 char*char*(3)int*ptr;/(3)int*ptr;/指指针针的的类类型型是是 int*int*(4)int(*ptr)3;/(4)int(*ptr)3;/指指针针的的类类型型是是 int(*)3int(*)3(5)int*(*ptr)4;/(5)int*(*ptr)4;/指指针针的的类类型型是是 int*(*)4in
12、t*(*)4怎怎么么样样?找找出出指指针针的的类类型型的的方方法法是是不不是是很很简简单单?2.2.指指针针所所指指向向的的类类型型当当你你通通过过指指针针来来访访问问指指针针所所指指向向的的内内存存区区时时,指指针针所所指指向向的的类类型型决决定定了了编编译译器器将将把把那那片片内内存存区区里里的的内内容容当当做做什什么么来来看看待待。从从语语法法上上看看,你你只只须须把把指指针针声声明明语语句句中中的的指指针针名名字字和和名名字字左左边边的的指指针针声声明明符符*去去掉掉,剩剩下下的的就就是是指指针针所所指指向向的的类类型型。例例如如:(1)int*ptr;(1)int*ptr;/指指针针
13、所所指指向向的的类类型型是是 intint(2)char*ptr;(2)char*ptr;/指指针针所所指指向向的的的的类类型型是是 charchar(3)int*ptr;(3)int*ptr;/指指针针所所指指向向的的的的类类型型是是 int*int*(4)int(*ptr)3;(4)int(*ptr)3;/指指针针所所指指向向的的的的类类型型是是 int()3int()3(5)int*(*ptr)4;(5)int*(*ptr)4;/指指针针所所指指向向的的的的类类型型是是 int*()4int*()4在在指指针针的的算算术术运运算算中中,指指针针所所指指向向的的类类型型有有很很大大的的作作
14、用用。指指针针的的类类型型(即即指指针针本本身身的的类类型型)和和指指针针所所指指向向的的类类型型是是两两个个概概念念。当当你你对对 C C 越越来来越越熟熟悉悉时时,你你会会发发现现,把把与与指指针针搅搅和和在在一一起起的的 类类型型 这这个个概概念念分分成成 指指针针的的类类型型 和和 指指针针所所指指向向的的类类型型 两两个个概概念念,是是精精通通指指针针的的关关键键点点之之一一。我我看看了了不不少少书书,发发现现有有些些写写得得差差的的书书中中,就就把把指指针针的的这这两两个个概概念念搅搅在在一一起起了了,所所以以看看起起书书来来前前后后矛矛盾盾,越越看看越越糊糊涂涂。3.3.指指针针
15、的的值值-或或者者叫叫指指针针所所指指向向的的内内存存区区或或地地址址指指针针的的值值是是指指针针本本身身存存储储的的数数值值,这这个个值值将将被被编编译译器器当当作作一一个个地地址址,而而不不是是一一个个一一般般的的数数值值。在在 3232 位位程程序序里里,所所有有类类型型的的指指针针的的值值都都是是一一个个 3232 位位整整数数,因因为为 3232 位位程程序序里里内内存存地地址址全全都都是是 3232 位位长长。指指针针所所指指向向的的内内存存区区就就是是从从指指针针的的值值所所代代表表的的那那个个内内存存地地址址开开始始,长长度度为为 si zeof(si zeof(指指针针所所指
16、指向向的的类类型型)的的一一片片内内存存区区。以以后后,我我们们说说一一个个指指针针的的值值是是 XXXX,就就相相当当于于说说该该指指针针指指向向了了以以 XXXX 为为首首地地址址的的一一片片内内存存区区域域;我我们们说说一一个个指指针针指指向向了了某某块块内内存存区区域域,就就相相当当于于说说该该指指针针的的值值是是这这块块内内存存区区域域的的首首地地址址。指指针针所所指指向向的的内内存存区区和和指指针针所所指指向向的的类类型型是是两两个个完完全全不不同同的的概概念念。在在例例一一中中,指指针针所所指指向向的的类类型型已已经经有有了了,但但由由于于指指针针还还未未初初始始化化,所所以以它
17、它所所指指向向的的内内存存区区是是不不存存在在的的,或或者者说说是是无无意意义义的的。以以后后,每每遇遇到到一一个个指指针针,都都应应该该问问问问:这这个个指指针针的的类类型型是是什什么么?指指针针指指的的类类型型是是什什么么?该该指指针针指指向向了了哪哪里里?(重重点点注注意意)4 4 指指针针本本身身所所占占据据的的内内存存区区指指针针本本身身占占了了多多大大的的内内存存?你你只只要要用用函函数数 sizeof(sizeof(指指针针的的类类型型)测测一一下下就就知知道道了了。在在 3232 位位平平台台里里,指指针针本本身身占占据据了了 4 4 个个字字节节的的长长度度。指指针针本本身身
18、占占据据的的内内存存这这个个概概念念在在判判断断一一个个指指针针表表达达式式(后后面面会会解解释释)是是否否是是左左值值时时很很有有用用。2 2、指指针针的的算算术术运运算算指指针针可可以以加加上上或或减减去去一一个个整整数数。指指针针的的这这种种运运算算的的意意义义和和通通常常的的数数值值的的加加减减运运算算的的意意义义是是不不一一样样的的,以以单单元元为为单单位位。例例如如:例例二二:char a20;char a20;int*ptr=int*ptr=(int*)(int*)a;a;/强强制制类类型型转转换换并并不不会会改改变变 a a 的的类类型型ptr+;ptr+;在在上上例例中中,指
19、指针针 ptrptr 的的类类型型是是 int*,int*,它它指指向向的的类类型型是是 intint,它它被被初初始始化化为为指指向向整整型型变变量量 a a。接接下下来来的的第第 3 3 句句中中,指指针针 ptrptr 被被加加了了 1 1,编编译译器器是是这这样样处处理理的的:它它把把指指针针 ptrptr 的的值值加加上上了了 sizeof(int)sizeof(int),在在 3232 位位程程序序中中,是是被被加加上上了了 4 4,因因为为在在 3232 位位程程序序中中,intint 占占 4 4 个个字字节节。由由于于地地址址是是用用字字节节做做单单位位的的,故故 ptrpt
20、r 所所指指向向的的地地址址由由原原来来的的变变量量 a a 的的地地址址向向高高地地址址方方向向增增加加了了 4 4 个个字字节节。由由于于 charchar 类类型型的的长长度度是是一一个个字字节节,所所以以,原原来来 ptrptr 是是指指向向数数组组 a a 的的第第 0 0 号号单单元元开开始始的的四四个个字字节节,此此时时指指向向了了数数组组 a a 中中从从第第 4 4 号号单单元元开开始始的的四四个个字字节节。我我们们可可以以用用一一个个指指针针和和一一个个循循环环来来遍遍历历一一个个数数组组,看看例例子子:例例三三:intint array20array20=0=0;inti
21、nt*ptr=array;*ptr=array;for(i=0;i20;i+)for(i=0;i20;i+)(*ptr)+(*ptr)+;ptr+ptr+;这这个个例例子子将将整整型型数数组组中中各各个个单单元元的的值值加加 1 1。由由于于每每次次循循环环都都将将指指针针 ptrptr加加 1 1 个个单单元元,所所以以每每次次循循环环都都能能访访问问数数组组的的下下一一个个单单元元。再再看看例例子子:例例四四:char a20=Youchar a20=You_ _areare_a_a_girl;girl;intint*ptr=*ptr=(int*)(int*)a;a;ptr+=5;ptr+
22、=5;在在这这个个例例子子中中,ptrptr 被被加加上上了了 5 5,编编译译器器是是这这样样处处理理的的:将将指指针针 ptrptr 的的值值加加上上 5 5 乘乘 sizeof(int)sizeof(int),在在 3232 位位程程序序中中就就是是加加上上了了 5 5 乘乘 4=204=20。由由于于地地址址的的单单位位是是字字节节,故故现现在在的的 ptrptr 所所指指向向的的地地址址比比起起加加 5 5 后后的的 ptrptr 所所指指向向的的地地址址来来说说,向向高高地地址址方方向向移移动动了了 2020 个个字字节节。在在这这个个例例子子中中,没没加加 5 5 前前的的 pt
23、rptr 指指向向数数组组 a a 的的第第 0 0 号号单单元元开开始始的的四四个个字字节节,加加 5 5 后后,ptrptr 已已经经指指向向了了数数组组 a a 的的合合法法范范围围之之外外了了。虽虽然然这这种种情情况况在在应应用用上上会会出出问问题题,但但在在语语法法上上却却是是可可以以的的。这这也也体体现现出出了了指指针针的的灵灵活活性性。如如果果上上例例中中,ptrptr 是是被被减减去去 5 5,那那么么处处理理过过程程大大同同小小异异,只只不不过过 ptrptr 的的值值是是被被减减去去 5 5 乘乘 sizeof(int)sizeof(int),新新的的 ptrptr 指指向
24、向的的地地址址将将比比原原来来的的 ptrptr 所所指指向向的的地地址址向向低低地地址址方方向向移移动动了了 2020 个个字字节节。下下面面请请允允许许我我再再举举一一个个例例子子:(:(一一个个误误区区)例例五五:#include#includeinint main()t main()char a20=char a20=YouYou_ _areare_a_a_girlgirl;char*p=a;char*p=a;char*ptr=&p;char*ptr=&p;/printf(printf(p=%dp=%d n,p);n,p);/printf(printf(ptr=%dptr=%d n,p
25、tr);n,ptr);/printf(printf(*ptr=%dptr=%d n,*ptr);n,*ptr);printf(*ptr=%cprintf(*ptr=%c n,*ptr);n,*ptr);ptr+;ptr+;/printf(printf(ptr=%dptr=%d n,ptr);n,ptr);/printf(printf(*ptr=%dptr=%d n,*ptn,*ptr);r);printf(*ptr=%cprintf(*ptr=%c n,*ptr);n,*ptr);误误区区一一、输输出出答答案案为为 Y Y 和和 o o误误解解:ptrptr 是是一一个个 charchar 的
26、的二二级级指指针针,当当执执行行 ptr+;ptr+;时时,会会使使指指针针加加一一个个sizeof(char),sizeof(char),所所以以输输出出如如上上结结果果,这这个个可可能能只只是是少少部部分分人人的的结结果果.误误区区二二、输输出出答答案案为为 Y Y 和和 a a误误解解:ptr:ptr 指指向向的的是是一一个个 char*char*类类型型,当当执执行行 ptr+;ptr+;时时,会会使使指指针针加加一一个个sizeof(char*)(sizeof(char*)(有有可可能能会会有有人人认认为为这这个个值值为为 1,1,那那就就会会得得到到误误区区一一的的答答案案,这这个
27、个值值应应该该是是 4,4,参参考考前前面面内内容容),),即即&p+4;&p+4;那那进进行行一一次次取取值值运运算算不不就就指指向向数数组组中中的的第第五五个个元元素素了了吗吗?那那输输出出的的结结果果不不就就是是数数组组中中第第五五个个元元素素了了吗吗?答答案案是是否否定定的的.正正解解:ptrptr 的的类类型型是是 char*,char*,指指向向的的类类型型是是一一个个 char*char*类类型型,该该指指向向的的地地址址就就是是p p的的地地址址(&p),(&p),当当执执行行ptr+;ptr+;时时,会会使使指指针针加加一一个个sizeof(charsizeof(char*)
28、*),即即&p+4;&p+4;那那*(&p+4)*(&p+4)指指向向哪哪呢呢,这这个个你你去去问问上上帝帝吧吧,或或者者他他会会告告诉诉你你在在哪哪?所所以以最最后后的的输输出出会会是是一一个个随随机机的的值值,或或许许是是一一个个非非法法操操作作.总总结结一一下下:一一个个指指针针 ptroldptrold 加加(减减)一一个个整整数数 n n 后后,结结果果是是一一个个新新的的指指针针 ptrnewptrnew,ptrnewptrnew 的的类类型型和和 ptroldptrold 的的类类型型相相同同,ptrnewptrnew 所所指指向向的的类类型型和和 ptroldptrold所所指
29、指向向的的类类型型也也相相同同。ptrnewptrnew 的的值值将将比比 ptroldptrold 的的值值增增加加(减减少少)了了 n n 乘乘sizeof(ptroldsizeof(ptrold 所所指指向向的的类类型型)个个字字节节。就就是是说说,ptrnewptrnew 所所指指向向的的内内存存区区将将比比 ptroldptrold 所所指指向向的的内内存存区区向向高高(低低)地地址址方方向向移移动动了了 n n 乘乘sizeof(ptroldsizeof(ptrold 所所指指向向的的类类型型)个个字字节节。指指针针和和指指针针进进行行加加减减:两两个个指指针针不不能能进进行行加加
30、法法运运算算,这这是是非非法法操操作作,因因为为进进行行加加法法后后,得得到到的的结结果果指指向向一一个个不不知知所所向向的的地地方方,而而且且毫毫无无意意义义。两两个个指指针针可可以以进进行行减减法法操操作作,但但必必须须类类型型相相同同,一一般般用用在在数数组组方方面面,不不多多说说了了。3 3、运运算算符符&和和*这这里里&是是取取地地址址运运算算符符,*是是间间接接运运算算符符。&a&a 的的运运算算结结果果是是一一个个指指针针,指指针针的的类类型型是是 a a 的的类类型型加加个个*,指指针针所所指指向向的的类类型型是是 a a 的的类类型型,指指针针所所指指向向的的地地址址嘛嘛,那
31、那就就是是 a a 的的地地址址。*p*p 的的运运算算结结果果就就五五花花八八门门了了。总总之之*p*p 的的结结果果是是 p p 所所指指向向的的东东西西,这这个个东东西西有有这这些些特特点点:它它的的类类型型是是 p p 指指向向的的类类型型,它它所所占占用用的的地地址址是是 p p所所指指向向的的地地址址。例例六六:int a=12;int a=12;int b;int b;int*p;int*p;int*ptr;int*ptr;p=&a;p=&a;/&a/&a 的的结结果果是是一一个个指指针针,类类型型是是 int*int*,指指向向的的类类型型是是/intint,指指向向的的地地址
32、址是是 a a 的的地地址址。*p=24;*p=24;/*p/*p 的的结结果果,在在这这里里它它的的类类型型是是 intint,它它所所占占用用的的地地址址是是/p p 所所指指向向的的地地址址,显显然然,*p*p 就就是是变变量量 a a。ptr=&p;ptr=&p;/&p/&p 的的结结果果是是个个指指针针,该该指指针针的的类类型型是是 p p 的的类类型型加加个个*,/在在这这里里是是 int*int*。该该指指针针所所指指向向的的类类型型是是 p p 的的类类型型,这这/里里是是 int*int*。该该指指针针所所指指向向的的地地址址就就是是指指针针 p p 自自己己的的地地址址。*
33、ptr=&b;*ptr=&b;/*ptr/*ptr 是是个个指指针针,&b&b 的的结结果果也也是是个个指指针针,且且这这两两个个指指针针/的的类类型型和和所所指指向向的的类类型型是是一一样样的的,所所以以用用&b&b 来来给给*ptr*ptr 赋赋/值值就就是是毫毫无无问问题题的的了了。*ptr=34;*ptr=34;/*ptr/*ptr 的的结结果果是是 ptrptr 所所指指向向的的东东西西,在在这这里里是是一一个个指指针针,/对对这这个个指指针针再再做做一一次次*运运算算,结结果果是是一一个个intint类类型型的的变变量量。4 4、指指针针表表达达式式一一个个表表达达式式的的结结果果
34、如如果果是是一一个个指指针针,那那么么这这个个表表达达式式就就叫叫指指针针表表式式。下下面面是是一一些些指指针针表表达达式式的的例例子子:例例七七:int a,b;int a,b;int array10;int array10;int*pa;int*pa;pa=&a;pa=&a;/&a/&a 是是一一个个指指针针表表达达式式。I Intnt*ptr=&pa;*ptr=&pa;/&pa/&pa 也也是是一一个个指指针针表表达达式式。*ptr=&b;*ptr=&b;/*ptr/*ptr 和和&b&b 都都是是指指针针表表达达式式。pa=array;pa=array;pa+;pa+;/这这也也是是指
35、指针针表表达达式式。例例八八:charchar*arr20;*arr20;charchar*parr=arr;*parr=arr;/如如果果把把 arrarr 看看作作指指针针的的话话,arrarr 也也是是指指针针表表达达式式charchar*str;*str;str=*parr;str=*parr;/*parr/*parr 是是指指针针表表达达式式str=*(parr+1);str=*(parr+1);/*(parr+1)/*(parr+1)是是指指针针表表达达式式str=*(parr+2);str=*(parr+2);/*(parr+2)/*(parr+2)是是指指针针表表达达式式由由于
36、于指指针针表表达达式式的的结结果果是是一一个个指指针针,所所以以指指针针表表达达式式也也具具有有指指针针所所具具有有的的四四个个要要素素:指指针针的的类类型型,指指针针所所指指向向的的类类型型,指指针针指指向向的的内内存存区区,指指针针自自身身占占据据的的内内存存。好好了了,当当一一个个指指针针表表达达式式的的结结果果指指针针已已经经明明确确地地具具有有了了指指针针自自身身占占据据的的内内存存的的话话,这这个个指指针针表表达达式式就就是是一一个个左左值值,否否则则就就不不是是一一个个左左值值。在在例例七七中中,&a&a 不不是是一一个个左左值值,因因为为它它还还没没有有占占据据明明确确的的内内
37、存存。*ptr*ptr 是是一一个个左左值值,因因为为*ptr*ptr 这这个个指指针针已已经经占占据据了了内内存存,其其实实*ptr*ptr 就就是是指指针针 papa,既既然然 papa 已已经经在在内内存存中中有有了了自自己己的的位位置置,那那么么*ptr*ptr 当当然然也也有有了了自自己己的的位位置置。5 5、数数组组和和指指针针的的关关系系数数组组的的数数组组名名其其实实可可以以看看作作一一个个指指针针。看看下下例例:例例九九:intarray10=0,1,2,3,4,5,6,7,8,9,value;intarray10=0,1,2,3,4,5,6,7,8,9,value;valu
38、e=array0;value=array0;/也也可可写写成成:value=*arvalue=*array;ray;value=array3;value=array3;/也也可可写写成成:value=*(array+3);value=*(array+3);value=array4;value=array4;/也也可可写写成成:value=*(array+4);value=*(array+4);上上例例中中,一一般般而而言言数数组组名名 arrayarray 代代表表数数组组本本身身,类类型型是是 int10int10,但但如如果果把把 arrayarray 看看做做指指针针的的话话,它它指指向
39、向数数组组的的第第 0 0 个个单单元元,类类型型是是 int*int*,所所指指向向的的类类型型是是数数组组单单元元的的类类型型即即 intint。因因此此*array*array 等等于于 0 0 就就一一点点也也不不奇奇怪怪了了。同同理理,array+3array+3 是是一一个个指指向向数数组组第第 3 3 个个单单元元的的指指针针,所所以以*(array+3)*(array+3)等等于于 3 3。其其它它依依此此类类推推。例例十十:charchar*str3=*str3=Hello,thisisasample!,Hello,thisisasample!,Hi,goodmorning.
40、,Hi,goodmorning.,HelloworldHelloworld;chars80chars80;strcpy(s,str0);strcpy(s,str0);/也也可可写写成成 strcpy(s,*str);strcpy(s,*str);strcpy(s,str1);strcpy(s,str1);/也也可可写写成成 strcpy(s,*(str+1);strcpy(s,*(str+1);strcpy(s,str2);strcpy(s,str2);/也也可可写写成成 strcpy(s,*(str+2);strcpy(s,*(str+2);上上例例中中,strstr 是是一一个个三三单单元
41、元的的数数组组,该该数数组组的的每每个个单单元元都都是是一一个个指指针针,这这些些指指针针各各指指向向一一个个字字符符串串。把把指指针针数数组组名名 strstr 当当作作一一个个指指针针的的话话,它它指指向向数数组组的的第第 0 0 号号单单元元,它它的的类类型型是是 charchar*,它它指指向向的的类类型型是是 charchar*。*str*str 也也是是一一个个指指针针,它它的的类类型型是是 charchar*,它它所所指指向向的的类类型型是是 charchar,它它指指向向的的地地址址是是字字符符串串Hello,thisisasample!Hello,thisisasample!
42、的的第第一一个个字字符符的的地地址址,即即HH的的地地址址。注注意意:字字符符串串相相当当于于是是一一个个数数组组,在在内内存存中中以以数数组组的的形形式式储储存存,只只不不过过字字符符串串是是一一个个数数组组常常量量,内内容容不不可可改改变变,且且只只能能是是右右值值.如如果果看看成成指指针针的的话话,他他即即是是常常量量指指针针,也也是是指指针针常常量量.str+1str+1 也也是是一一个个指指针针,它它指指向向数数组组的的第第 1 1 号号单单元元,它它的的类类型型是是 char*char*,它它指指向向的的类类型型是是 char*char*。*(str+1)*(str+1)也也是是一
43、一个个指指针针,它它的的类类型型是是 char*char*,它它所所指指向向的的类类型型是是 charchar,它它指指向向 Hi,goodmorning.Hi,goodmorning.的的第第一一个个字字符符HH下下面面总总结结一一下下数数组组的的数数组组名名(数数组组中中储储存存的的也也是是数数组组)的的问问题题:声声明明了了一一个个数数组组 TYPETYPE arraynarrayn,则则数数组组名名称称 arrayarray 就就有有了了两两重重含含义义:第第一一,它它代代表表整整个个数数组组,它它的的类类型型是是 TYPEnTYPEn;第第二二,它它是是一一个个常常量量指指针针,该该
44、指指针针的的类类型型是是 TYPE*TYPE*,该该指指针针指指向向的的类类型型是是 TYPETYPE,也也就就是是数数组组单单元元的的类类型型,该该指指针针指指向向的的内内存存区区就就是是数数组组第第 0 0 号号单单元元,该该指指针针自自己己占占有有单单独独的的内内存存区区,注注意意它它和和数数组组第第 0 0 号号单单元元占占据据的的内内存存区区是是不不同同的的。该该指指针针的的值值是是不不能能修修改改的的,即即类类似似 array+array+的的表表达达式式是是错错误误的的。在在不不同同的的表表达达式式中中数数组组名名 arrayarray 可可以以扮扮演演不不同同的的角角色色。在在
45、表表达达式式 sizeof(array)sizeof(array)中中,数数组组名名 arrayarray 代代表表数数组组本本身身,故故这这时时sizeofsizeof 函函数数测测出出的的是是整整个个数数组组的的大大小小。在在表表达达式式*array*array 中中,arrayarray 扮扮演演的的是是指指针针,因因此此这这个个表表达达式式的的结结果果就就是是数数组组第第 0 0 号号单单元元的的值值。sizeof(*array)sizeof(*array)测测出出的的是是数数组组单单元元的的大大小小。表表达达式式 array+narray+n(其其中中 n=0n=0,1 1,2 2,
46、.)中中,arrayarray 扮扮演演的的是是指指针针,故故 array+narray+n 的的结结果果是是一一个个指指针针,它它的的类类型型是是 TYPETYPE*,它它指指向向的的类类型型是是 TYPETYPE,它它指指向向数数组组第第 n n 号号单单元元。故故 sizeof(array+n)sizeof(array+n)测测出出的的是是指指针针类类型型的的大大小小。在在 3232 位位程程序序中中结结果果是是 4 4例例十十一一:intint array10;array10;intint(*ptr)10;(*ptr)10;ptr=&array;ptr=&array;:上上例例中中 p
47、trptr 是是一一个个指指针针,它它的的类类型型是是 int(*)10int(*)10,他他指指向向的的类类型型是是int10int10,我我们们用用整整个个数数组组的的首首地地址址来来初初始始化化它它。在在语语句句 ptr=&arrayptr=&array中中,arrayarray 代代表表数数组组本本身身。本本节节中中提提到到了了函函数数 sizeof()sizeof(),那那么么我我来来问问一一问问,sizeof(sizeof(指指针针名名称称)测测出出的的究究竟竟是是指指针针自自身身类类型型的的大大小小呢呢还还是是指指针针所所指指向向的的类类型型的的大大小小?答答案案是是前前者者。例
48、例如如:int(*ptr)10;int(*ptr)10;则则在在 3232 位位程程序序中中,有有:sizeof(int(*)10)=4sizeof(int(*)10)=4sizeof(int10)=40sizeof(int10)=40sizeof(ptr)=4sizeof(ptr)=4实实际际上上,sizeof(sizeof(对对象象)测测出出的的都都是是对对象象自自身身的的类类型型的的大大小小,而而不不是是别别的的什什么么类类型型的的大大小小。6 6、指指针针和和结结构构类类型型的的关关系系可可以以声声明明一一个个指指向向结结构构类类型型对对象象的的指指针针。例例十十二二:struct M
49、yStructstruct MyStruct int a;int a;int b;int b;int c;int c;struct MyStruct ss=20,30,40;struct MyStruct ss=20,30,40;/声声明明了了结结构构对对象象 ssss,并并把把 ssss 的的成成员员初初始始化化为为 2020,3030 和和 4040。struct MyStruct*ptr=&ss;struct MyStruct*ptr=&ss;/声声明明了了一一个个指指向向结结构构对对象象 ssss 的的指指针针。它它的的类类型型是是/MyStructMyStruct*,*,它它指指向向
50、的的类类型型是是 MyStructMyStruct。int*pstr=(int*)&ss;int*pstr=(int*)&ss;/声声明明了了一一个个指指向向结结构构对对象象 ssss 的的指指针针。但但是是 pstrpstr 和和/它它被被指指向向的的类类型型 ptrptr 是是不不同同的的。请请问问怎怎样样通通过过指指针针 ptrptr 来来访访问问 ssss 的的三三个个成成员员变变量量?答答案案:ptrptr-a;a;/指指向向运运算算符符,或或者者可可以以这这们们(*ptr).a(*ptr).a,建建议议使使用用前前者者ptrptr-b;b;ptrptr-c;c;又又请请问问怎怎样样