强制类型转换中“自以为是”的问题

来源:互联网 发布:淘宝销售计划书 编辑:程序博客网 时间:2024/06/11 09:59

一、“自以为是”引发的错误

1、问题来源:

# include <iostream>using namespace std;int main (void){    int i = -185;    int * p = &i;    char * q = (char *)p;    char ch = *q;    cout << ch << '\t' << (short)ch << '\t' << (int)ch << endl;    cout << (char)i << '\t' << (short)i << '\t' << i << endl;    return 0;}

最近在学习C++,闲来无事突发奇想随便写了几行代码,如上所示。本以为输出结果会是:

G   -185    -185G   -185    -185Press any key to continue

而最终结果却是:

G   71  71G   -185    -185Press any key to continue

2、这种错误想法的来源

如下图:
int x = -185在内存中的二进制存储:
int x = -185在内存中的二进制存储

错误出就出在了误以为ch的内存,就是q指向的地址,即0X18FF3C这一个字节,并以此错误为基础认为:

ch 是1000 0111十进制为7171的ASCII对应字符G;那么(short)ch当然是占用了0X18FF3C0X18FF3D两个字节,其二进制为1111 1111 1000 0111,所以结果为-185;(int)ch则占用了x的所有四个字节内存,结果依然为-185

自以为是这样,而实际并非如此,即“自以为是而以人为非也”。那么真正的存储形式是怎样的呢?

二、问题的关键所在

1、系统为ch分配的内存在哪?

首先我们来看变量ch的地址测试结果:
变量ch的内存地址和指针q的指向地址

注意测试时,由于cout的特性需要在&ch和q前加上(int *),否则输出的就是字符形式的类似于乱码的地址了。由测试结果可以看出,指针q的指向和指针p的指向相同,但是ch的地址并非“自以为是”的q指向的地址。而是下图所示的存储形式:

测试结果:
测试结果

存储形式:
内存存储

2、解释所有问题:

这样就可以解释为什么,强制转换x和强制转换ch的输出结果有差异的问题了:

(1)、ch的地址并非q指向的地址,q指向的地址也并非为ch所占有,只是ch通过*q读取了q指向地址的存储值1000 0111,并复制了该二进制到自己所占有的内存之中即0X18FF30。而强制类型转换(short)ch,(int)ch都只读取了ch仅有的1000 0111,所以其值也为71(或者G)。
(2)、对于如何通过ch和*q的区别,我们可以用以下代码具体地完全地区分开(对于C++的cout使用时的细节还不是特别熟悉。所以用C代码测试):

# include <stdio.h>int main (void){    int i = -185;    int * p = &i;    char * q = (char *)p;    char ch = *q;    printf("%d\t%d\t%c\n", i,(short)i, (char)i);    printf("%d\t%d\t%c\n", *p, *((short*)p), *(char *)p);    printf("%d\t%d\t%c\n", *((int *)q),  *((short *)q) ,*q);    printf("%d\t%d\t%c\n", (int)ch, (short)ch, ch);    printf("%#x\t%#x\t%#x\n", i,(short)i, (char)i);    printf("%#x\t%#x\t%#x\n", *p, *((short*)p), *(char *)p);    printf("%#x\t%#x\t%#x\n", *((int *)q),  *((short *)q) ,*q);    printf("%#x\t%#x\t%#x\n", (int)ch, (short)ch, ch);    return 0;}

代码运行结果为:

-185    -185    G-185    -185    G-185    -185    G71      71      G0xffffff47      0xffffff47     0x470xffffff47      0xffffff47     0x470xffffff47      0xffffff47     0x470x47    0x47   0x47Press any key to continue

q是指向x地址首字节的指针,只要将其类型char * 强制转换成int * ,其特点与属性就与指针p完全相同,也对x有了完全的操作权限。而ch仅仅是x地址首字节存储内容的拷贝,和x没有任何直接关系 。

1 0
原创粉丝点击