C++从零开始之指针及其语义和运用
quo;()”、函数调用规则“__stdcall”、偏移“<自定义类型名>::”、常量“const”和地址类型修饰符。其中的地址类型修饰符是最混乱的。
在《C++从零开始(三)》中已经说明地址在32位操作系统中就是一个数,这个数经常以32位长的二进制数表示,以唯一标识一特定内存单元。而一个数字的类型是地址类型时(因为有地址类型修饰符,就好像一个数字是数组类型时),就将这个数字所代表的数学意义上的数用二进制表示,以标识出一个内存单元,然后按照原类型的规则来解释那块内存单元及其后续单元的内容(类型的长度可能不止一个字节,而地址类型是类型修饰符,故一定有原类型)。由于变量映射的数实际是地址,故变量所映射的数字就是地址类型的。如long a;,假设a映射的是3006,当书写a = 3;时,由于a是变量名,故返回a所映射的数字3006,类型是long类型的地址类型。由于是地址类型,“=”操作符的语法检查成功(这是类型的另一个用处——语法检查,就好像动名形容词一样),执行“=”操作符的计算。 应注意C++并未提出地址类型修饰符这个概念,只是我出于语法上的完备而提出的,否则要涉及更多的无谓概念和规则,如*( p + 1 ) = 20; a[2] = 3;等的解释将复杂化,故在《C++从零开始》系列中提出地址类型的数字这个概念,旨在以尽量少的概念解释尽量多的语法。 最常用的类型修饰符——指针和数组 在《C++从零开始(五)》中已说明指针只是一种类型修饰符。一个数字是指针类型时,将这个数字所代表的数学意义上的数用二进制表示并返回。前面已说过数字的用处就是转换其代表的数为二进制数,其类型仅说明如何转换,而指针类型所代表的规则就是按数学规则变成二进制数,而不管其原类型是何种类型。由于不受原类型的影响,故指针类型总是固定长度(对成员指针则不一定),在32位操作系统上是四个字节。 如long a; long *p = &a;。假设a映射的是3006,p映射的是3010.对于*p = 3;,p这个操作符返回类型为long的指针类型的地址类型的数字3010,即这个数字的类型被两个类型修饰符两次修饰,由于最后是被地址修饰,故3010是地址类型的数字,而其原类型是long的指针类型。故*p返回类型为long类型的地址类型的数字3006,然后执行“=”操作符的计算。 这里请注意两个操作符——取内容操作符“*”和取地址操作符“&”。在《C++从零开始(五)》中也强调过,它们其实名不副实,应该叫类型转换操作符才对。即前者后接指针类型的数字,返回的数字原封不动,仅将其类型变为地址类型;后者后接地址类型的数字,返回的数字原封不动,仅将其类型变为指针类型。这有点耍小聪明的感觉,但请注意:long *p1 = 0; long *p2 = &*p1;如果“*”的操作是取内容,则&*p1将先取地址为0的内存单元的内容,这将引起内存访问违规,但实际并不会,因为“*”仅转换类型而非取内容(取内容是由地址类型的数字的计算来实现的)。 前面已说明,在指针类型的数字返回二进制数时,并不需要原类型的参与,即类型为long*的数字3006和类型为char*的数字3006返回的二进制数都一样,都是3006对应的二进制数。那么为什么要让指针是类型修饰符以带个不用的原类型?根据前面即可看出指针类型的原类型是给取内容操作符“*”用的。但它还有个用处,因为数组类型修饰符的加入,使得指针多了一个所谓的运算功能,在此先看看数组类型。 在《C++从零开始(五)》中已详细说明数组的修饰功能是将原类型的元素重复多个连续存放以此形成一个新的类型。如long a[10];,a的类型就是long[10],长度为10 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |