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

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

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    -185
G   -185    -185
Press any key to continue

而最终结果却是:

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

2、这种错误想法的来源

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

这里写图片描述

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

ch 是0100 0111十进制为7171的ASCII对应字符G;
那么(short)ch当然是占用了0X18FF3C0X18FF3D两个字节,其二进制为1111 1111 0100 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指向地址的存储值0100 0111,并复制了该二进制到自己所占有的内存之中即0X18FF30。而强制类型转换(short)ch,(int)ch都只读取了ch仅有的0100 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    G
71      71      G
0xffffff47      0xffffff47     0x47
0xffffff47      0xffffff47     0x47
0xffffff47      0xffffff47     0x47
0x47    0x47   0x47
Press any key to continue

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值