关闭

指针的强制类型转换思考

977人阅读 评论(0) 收藏 举报

以前都没怎么特意的注意指针的强制类型转换。对于int *a=(int*)malloc(sizeof(int)*4);这样的语句感觉这样写都是理所当然的,因为要赋值的话两边的数据类型至少要一样吧。当时对于指针的强制类型转换在内存中的体现没有什么本质的认识。
在编程中,指针的强制类型转换引起我认真注意的是在对位图的操作中,在那段读写位图文件的代码函数中大量的用到了指针的强制类型转换,本篇文章也会以那段代码来做文章的了结。

为了认识指针的强制类型转换,我在程序中写入这么一段代码:

#include "stdafx.h"
#include <iostream.h>
struct student//学生
{
char *name;
int old;
};
struct CLASS//班级
{
student st;
int nunb;
};
int main(int argc, char* argv[])
{
CLASS cla; //班级对象
cla.nunb=29;
cla.st.name="liunian";
cla.st.old=22;
cout<<&cla<<endl;
student *st=(student*)&cla;
cout<<st<<endl;
st->name="yixiaobing";
st->old=21;
cout<<cla.st.name<<endl;
return 0;
}//可能名字不规范,将就着看吧


可以看到指针的强制类型转换后他的值是不会变的, 再怎么转换,他指的不还是他块地址吗!所以指针值不会变,变的是指向那块地址的数据类型。而什么是数据类型,为什么要数据类型。我把上面的main函数中的代码改变一下:

#include "stdafx.h"
#include <iostream.h>
#include "Fish.h"
#include "Animal.h"
struct student
{
char *name;
int old;
};
struct CLASS
{
student st;
int nunb;
};
int main(int argc, char* argv[])
{
student st;
st.name="liunian";
st.old=21;
CLASS *cla=(CLASS *)&st;
cla->st.name="yixiaobing";
cout<<st.name<<endl;
return 0;
}
//我改变的也就是这次先定义的是学生对象,而学生和班级指针互换一下。

可以看到访问正常!但是我们再在上面的代码中稍微改动一点
student st;
st.name="liunian";
st.old=21;
CLASS *cla=(CLASS *)&st;
cla->nunb=29; //加入了这么一句代码。
cla->st.name="yixiaobing";
cout<<st.name<endl;

访问出错了!好了不卖关子了。写了这么多也就是为了说明两点:
1.指针的强制类型转换,可以任意的转换,你完全不需要在乎在转换前=左右的数据类型。你要在乎的是转换后的数据类型是一样的就行了。指针的强制类型转换对于那块内存其实什么也没有做,只是改变了数据类型,改变了数据类型,其实那个内存中的数据什么也没有被改变,以前的二进制数据还是那些二进制数据,只是不同的数据类型读取的方式不同,比如,int型一下读取4字节,char[10]读取10字节而已

2.转换了是为了用指针变量来访问数据的。那怎么来访问数据呢?就是数据类型了。int类型的变量在你转换的指针指向的那块内存中找这个变量,看有没有,如果没有的话,就上面的cla->nunb=29; 这个变量在内存中是没有的。因为开始内存中的数据时student的,自然就没有这个变量了。所以访问错误。

关于指针的强制类型转换我还像提一点。孙鑫的书上,在讲解虚函数的时候有举到一个例子,书48页。
class CAnimal //动物类
{
public:
CAnimal();
virtual ~CAnimal();
public:
void breash();

};
CAnimal::CAnimal()
{
cout<<"animal is constructed"<<endl;
}

CAnimal::~CAnimal()
{
cout<<"animal is xi"<<endl;
}
void CAnimal::breash()
{
cout<<"annimal is breashing"<<endl;
}

class CFish:public CAnimal//鱼类
{
public:
CFish();
virtual ~CFish();
public:
void tupaopao();
};
CFish::CFish()
{
cout<<"fish is constructed"<<endl;
}

CFish::~CFish()
{
cout<<"fish is xigou"<<endl;
}
void CFish::tupaopao()
{
cout<<"fish is tupaopao"<<endl;
}


int main(int argc, char* argv[])
{
CFish fish;
cout<<endl;
cout<<&fish<<endl;
CAnimal *animal=(CAnimal *)(&fish);
cout<<animal<<endl;
animal->breash();
cout<<endl;
return 0;
}

没有好基础的同学可以注意一下继承时子类和父类的构造函数和析构函数调用顺序哦,
上面的显示结果为什么会是这样我就不说了,孙鑫书上说的很清楚,我写文章从来不喜欢抄书。下面对比一下下面的代码(主要是改变main函数)

int main(int argc, char* argv[])
{

CAnimal animal;
cout<<&animal<<endl;
CFish* fish=(CFish*)&animal;
cout<<fish<<endl;
fish->tupaopao();
return 0;
}

如果有认真看代码的人应该注意到了一个问题了。本来fish的tupaopao在内存中本来是没有的,但是却为什么没有像上面一下访问出错了呢?到这是类的特权?没有的内存的会在内存中为它分配?不知道,反正他访问没有出现问题。
其实我是一直不喜欢光想这种纯理论的东西的。如果你觉得你对指针强制类型没有问题的话,可以去拿来解决一下实际的问题:位图的读写。代码请参加另一篇文章:

动态显示BMP位图

 

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:276020次
    • 积分:2828
    • 等级:
    • 排名:第12671名
    • 原创:90篇
    • 转载:1篇
    • 译文:0篇
    • 评论:75条
    文章分类
    最新评论