指针的那些事-----初窥指针的强制转换

查了下书,指针是这样定义的:“指向某种类型对象的复合数据类型”。“复合数据类型”这句说得很好,因为一般说道都会想到“就是地址”,说开无非是存着所指向对象的地址呗?但是如果单单说是一个存有地址的类型这显然不够称得上“复合类型”。

  不妨再加上一条:1.存着所指对象地址。2.存着所指对象类型和类型大小。虽然指针远没这么简单(并且一个指针变量4个字节存的仅仅是32位的地址,本篇为了给你一种感觉暂且说同时存了“类型和类型大小”,下篇会给出另外的解释),但是我们看看这两条都能做些什么。

  第一条应该没什么好解释的了,第二条有必要说说,因为看似很显然,但是可以明白好多事情。

  试想我们定义一个某类型指针p,后可以p++,p--,*p这些都与“指针记录了所指对象类型大小”有关,不然p++和p--  一次跳了多远?还有*p一次取了多长,都是由记录的类型大小决定的:如int *p=&i;那么++ 一次至少会跳int那么远即4个字节(连续存储下),*p一次也会从p所指向地址为起点取出int那么长(4字节)空间的二进制信息,并将这些二进制翻译成“指针内部存着的其所指向的类型”的类型。记住这种“感觉”:初始化指针就是:(1)记下所指对象的地址(2)同时记下所指类型和类型大小。(3)对一个指针解引用(*p)就是从指针所指地址为起点,读出所指类型大小那么大的空间的二进制,然后将二进制翻译成所指类型。(4)而++,——操作就是向前或向后跳所指类型那么大小的空间

下面强化一下。

 

[cpp]  view plain copy
  1. int t = 65<<8;   
  2. char *p = (char*)&t+1;   
  3. cout<<(int)*p<<endl;  

  65左移了8位然后被给一个被赋值给整型t,然后定义了char*指针p,而后的强制转换就有些意思了,按照前面的感觉也就不难理解了:取了t的地址然后由于遇见(char*),p存储的类型原本应该是t的类型int,然而由于(char*)的出现p中存储的类型将变成char类型,大小也为char那么大即一个字节,而后+1,这时这一跳将因为目前对象是char类型,而只跳一个字节(8位),也就是说这时p将指向之前左移8位的65这个数所在内存那么下面的cout将如期望的一样输出65这个数。

  我们有了感觉之后似乎对指针间的强制类型转换也很清楚了:(1)转换后的指针中记录的地址依旧是转换前的地址(2)转换后的指针记下的所指类型和类型大小,为强制转换的类型和强制转换类型的大小。(3)*操作会依旧会以指针所指地址为起点,却取出转换后的指针所记录的类型大小那么大的空间的二进制,翻译成指针转换后的所指类型。(4)转换后的++,和--跳的距离以转换后的指针中存放的类型大小为依据

 

  那么我们更有感觉了:只要指针间在“能转换的情况下”我们就可以转来转去,只要保证不对指针进行移位就可以保证指针所指向地址一直不变,转换仅仅转的是里面存的类型和类型大小,只要我们最后能转回原来的类型还可以如同最初时一样按原类型操作它。

 

[cpp]  view plain copy
  1. typedef struct   
  2. {  
  3.    int a;  
  4. }test;  
  5.   
  6. test t;  
  7. t.a=100;  
  8.   
  9.   
  10. long* t1=(long*)&t;  
  11. char* t2=(char*)t1;  
  12. test * t3=(test*)t2;  
  13. cout<<t3->a<<endl;//output:100  

  转来转去又转回初始类型,如我们所愿的输出100。

  最后确认一下感觉。

 

[cpp]  view plain copy
  1. int i=*(int *)"ABC";  
  2. cout<<i<<endl;//output:4407873  

 4407873是什么看不清楚吗?转成二进制10000110100001001000001,还看不清?补齐四个字节,再分割一下,00000000'01000011'01000010'01000001。不知道是什么了吗?对照下表:

 二进制数        ASCII(也是%d输出的整型值)       字符

01000001                   65                               A

01000010                   66                               B

01000011                   67                               C

00000000                    0                               /0 

  又很有感觉了吧?对于上面的程序中原本ABC/0(字符串隐含/0下一篇会解释)是一坨二进制,生成后返回地址char*类型然后遇到 (int *)被转成了int*,就等于告诉程序:以后对待存ABC和/0这坨内存别再看成是char*的了,而是我int*的了,要读的话别读char*那样的一个字节了,要给我读满4个字节(int是4个字节),也就是后再遇到*解引用,取出4个字节的东西赋值给i,而i是int型,00000000'01000011'01000010'01000001这串二进制自然翻译成int型的即4407873。

  最后,忘了这一切吧,记住一句话“永远别玩指针!玩不好容易被指针玩”,以上的一切代码都不是好习惯,只是为了给你一种感觉,记住那句话,再记住感觉(下一篇还要用到这种感觉)就足够了。

转载于:https://my.oschina.net/alphajay/blog/60893

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值