指针漫谈

 
  #数据的意义依赖于解释
    在一块存储区域内,存有数据,但是数据代表了什么,却依赖于解释!对于一个计算机内
    32位长度的二进制数据来说,你认为它是int型,它就是整型;你认为它是unsinged int,它就
    是无符号数。
 对于指针也是如此,如果不依赖于型别(type)的区分,它在数据的层面上与其他类型没有区别。
 +----------+
 +   byte   +
 +----------+
 +   byte   +                                       解释
 +----------+      ----->(int ? ,uint ? ,pointer ?) ----> 确定下来
 +   byte   +
 +----------+
 +   byte   +
 +----------+
 
  #指针代表一块内存区域的地址信息

  按照这样的信息在指针的某种约定运算,可以“寻的”到这块内存区域。  一般意义上的指针是,指向一块内存区域。作为数值,因为指针也是一个变量,存储的是这块逻辑区域的首地址。 利用*pointer *运算,可以取得所指向区域的信息。其中执行的运算是,从指针取出地址,按照地址和指针的型别,读取 按照型别可以计算出来多少个字节的信息。


 +------------------+    读取其值作为内存某地首地址                     一块区域信息
 +  pointer value    +   -------------------------->      +sizeof(type)     +----------+
 +------------------+                                                          +           +
                                                                                                 +  byte    +
                                                                                  +----------+
                                                    +             +
                                                                      +  byte    +
                                                                                 +-----------+
                                       +  more   +
                                                      +  byte ... +
                                                                                 +-----------+
                                                      


  #区域是一块内存划分,可以具有各种地形地貌,可以是一马平川的平原,这块种西瓜,那块种东瓜,这里还放一个小小的池塘;
  也可以是深不可测的深渊,在数据结构中加入指针,穿针引线地形成空中楼阁,从平面结构走向多维立体结构。
  内存区域所容许的结构,只受限于你的想象能力。从这点也可以看出,所谓的“数据依赖于解释”,解释是多么神奇的魔棒。我们最常见的结构有数组、表、树、图等。
  
    +---------------------+
    +       池塘             +
    +--------+-----------+    
    + 西瓜   +  东瓜   +
    +-------------+------+
    +  房子      + 花园+
    +---------------------+
   
    池塘
    +-------------------+
    +  int 长              +
    +-------------------+
    +  int 宽              +
    +-------------------+                       
    +  int 水深          +
    +-------------------+
    +  char[256]      +
    +  户主名称       +
    +   ... ...               +
    +-------------------+

  可以将区域形式化定义为:
  区域(block)  =   区域 (block)                      | 原始类型(内建类型)
                                  | 区域指针(block pointer)   | 原始类型指针(pointer)

  可见区域是一个可以递归的概念,递归的终点在于原始基本类型,一切类型都是在原始基本类型的基础上进行构建,这些原始基本类型类似建筑,是盖起程序的“砖瓦”。
 
  #指针的运算
   指针一些加减运算和逻辑运算都是一些比较简单的概念,其中需要重视的概念,甚至于要牢记的的知识。即,指针在进行加减运算时,移动的单位,是以自己指针所代表的型别为单位的,
  

  即 pointer + offset  =(地址意义) 首地址 + offset*sizeof(pointer type)字节。

   关于指针来讲,最神奇的运算在于强制类型转换了,其实可以简单来理解为,从当前地址开始以什么来解释这块区域内的数据。

   所以 即使 char s[] =  "hello world! I love c language!"

   实际上,你通过 int  i  =  *(int*)s,进行指针的强制类型转换,就指示计算机从s开始地址,以整型去取得“区域”所存储的值。 这个可能看起来没有什么用,其实,你还没有看到它的价值。在windows消息映射泵中,消息的处理函数一般拥有简单的。onMessage(WPARAM wParam, LPARAM lParam)形式,消息处理函数内部,根据消息泵出windows和泵入处理器之间约定, 对于传过来的wParam进行相应的转型或处理后转型,得到有用的信息。这样作的好处是,可以使消息的处理函数具有统一的注册形式, 便于管理,至少可以在消息标识MessageID 与 pHandlerFunction间建立比较容易的“映射”机制,而且扩展性也比较好!


   但是,值得说明的是,指针转型是很危险的,因为你很难杜绝用户将指针转为完全风马牛不相及、任意类型的指针,因为指针的转型后的意义,一般可以看成从此地开始以这种解释去解释。
   那么对于,类似的代码,你就可以看出它的破坏性,这一般会导致程序崩溃的。
    
     typedef void (*pFunction)();
     char char s[]    =  "hello world! I love c language!"
     pFunction     pf = (pFunction)(void *)s;
                
   pf();
    
     //以函数形式执行,呵呵,你就知道危害性是有多大了吧。。。
     //可见有些解释是福音,有些解释确实歪理邪说,一般来讲拥有最终的解释权
     //是没有坏处的,这就是为什么很多组织抽奖,活动的举办者都要特殊声明,拥有最终的解释权 :)

  格言:在指针转型方面,千万不要给你的用户太多权限,因为你永远无法预料他的好意或歹意。
 
  #指针与简单的序列化
  指针在序列化方面扮演很重要的角色,简直是数据依赖于解释的一个很重要的体现。
  假设从持久化资源或网络中传过来一些数据,由于在这些领域内最多只能见到字符级别、层面的信息,和二进制强不到那里去!字符级信息也只是在二进制基础上封装了 八个bit作为读取单位,并且详细地规定了八个bit所形成的0--255区间内,所有值的字符含意。在有些极端情况下就是需要Raw Data,连字符意义都剥除了的二进制数据。
  在下面举例的简单的序列化过程中,我们面对的信息也是Raw Data,这些Raw Data在形成的时候,被根据先后顺序,按照约定和自描述形式的二进制数据写入,例如,在32环境中,直接将int写为 四个字节的二进制数据,字符串信息,根据应用需要可以设定 字符二进制数据信息前必须带字符长度信息。而这些基本的写入方法确定后,整体信息上应该怎么解呢?
  这个就赖于先后写,那个序列有关了,这也是序列化,那个“序”的基本字源吧。

  例如:
  struct  A
  {
 
    int i ;
    char s[8] ;  
    floadt f ;


  }
 
  class Buffer4Serialize
  {
     byte  data[someSize]


  }
 A a --->序列化,借用c++重载运算符的表示法
 
     
        
   Buffer4Serialize   data;
   a.i >> data;
   s   >> data;//为了自描述,这个过程中不但要写入内容还要写入字符串的长度
  
A  aClone --->反序列化
         Buffer4Serialize   data;

     
 
  aClone.i << data;
   s       << data; //由于是自描述的,序列化知道应该向s写多少个字节

 

     //
     发生在其中的强制类型转换
     a.i >> data
     实际上会发生 *(int*)(data + offset)  = a.i
     a.i << data
     实际上会发生   a.i  = *(int*)(data + offset)

#数据意义依赖于解释,数据又来自那里呢?
  前面一直强调,数据的意义依赖于你对它的解释,好像是解释晚于数据。但是,并不如此,数据从何而来呢?一般来说,数据是一种对现实世界的映射,和现实的某个状态相对应
注意在有“状态”意义的时间,实际上已经有某种程度上的解释的,解释先于了数据产生。
  我们前面作的有数据后再来解释,只不过是为了演示指针的强悍,当指针的强悍能发挥巨大威力的时候,往往是那种解释是符合了最初产生它的那个解释或相容。不然就是流氓行为了。


 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值