强制类型转换的造成的后果

bothsky 2008-06-06 06:21:43
小弟对强制类型转换的细节不是很清楚,在这里请教大家一下。
如: 结构体A{int a1;
int a2;
char a3;
int *a4;}

结构体B{
char b1;
int b2;
int b3;
char b4;}
A *a={。。。};//A的初始化
B *b;
b=(B*)a;//此时在内存中b的内容应该是B的定义格式,还是A的格式。
此时编译可以通过,但是运行异常。在a的初始化的时候就出现错误。
请高手给详细讲解一下强制类型转换时,内存是如何调整的。
...全文
353 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
bothsky 2008-06-10
  • 打赏
  • 举报
回复
明白各位的意思了,是访问规则出现问题导致的;
iu_81的demo中使用了#pragma pack(1),这样的话是不是就可以解决访问规则不一致的问题?:)
野男孩 2008-06-07
  • 打赏
  • 举报
回复
弄清楚数据在内存中的布局就清楚了,数据没有变,访问方式不适当自然会有问题。
hazuki9902 2008-06-07
  • 打赏
  • 举报
回复
[Quote=引用楼主 bothsky 的帖子:]
小弟对强制类型转换的细节不是很清楚,在这里请教大家一下。
如: 结构体A{int a1;
int a2;
char a3;
int *a4;}

结构体B{
char b1;
int b2;
int b3;
char b4;}
A *a={。。。};//A的初始化
B *b;
b=(B*)a;//此时在内存中b的内容应该是B的定义格式,还是A的格式…
[/Quote]
zzhprogram 2008-06-06
  • 打赏
  • 举报
回复
关注!问一下,结构体指针可以直接: A *a={。。。};//A的初始化 ?
zzyjsjcom 2008-06-06
  • 打赏
  • 举报
回复
1. 内存布局没有变化
2. 访问大小发生了变化
xhd3767 2008-06-06
  • 打赏
  • 举报
回复
C不支持动态识别机制的..这样的话就不能很好的处理这类问题......
所以C++里面有续函数..有了向上转型....
iu_81 2008-06-06
  • 打赏
  • 举报
回复

1,结构体指针强制类型转换的问题

2,char字符cout输出的问题

3,结构体数据对齐的问题 具体下面的实例有分析

#include <iostream>

using namespace std;

#pragma pack(1)

typedef struct msg{

unsigned char id;

unsigned char cmd;

unsigned char byte[4];

} MSG;

typedef struct cemsg{

unsigned char id;

unsigned char cmd;

unsigned char data[10];

} CEMSG;

typedef struct msg_p{

unsigned char id;

unsigned char cmd;

unsigned char* ptr;

} MSG_P;

int main(){

/****** 注意:

1. 用void*输出char变量的地址,对于char变量的应用的cout输出,

认为是char*,输出它的 内容

2. 从本次测试来看,指针的类型转换,其实是一种虚拟转换,只是用新结构来解析老结构

在本例中可以明显体会。

*****/

void* addr;

MSG msgTemp = { 0x0c, 0x11, {0xD4,0x00,0xFF,0x00} };

MSG* d_OsMsgPtr = &msgTemp; MSG_P* d_p;

/*CEMSG和MSG都是数组,数据对齐没有空缺,转换没有问题

CEMSG* d_p;

d_p = (CEMSG*) d_OsMsgPtr; */

cout << "size of MSG : " << sizeof(MSG)

<< "size of CEMSG : " << sizeof(CEMSG) << "--" << sizeof(unsigned char*)

<< "size of MSG_P : " << sizeof(MSG_P) << endl;

cout << "msgTemp : " << " id = " << msgTemp.id

<< " cmd = " << msgTemp.cmd

<< " byte = " << msgTemp.byte << endl;

cout << "d_OsMsgPtr : " << d_OsMsgPtr->id

<< d_OsMsgPtr->cmd << d_OsMsgPtr->byte << endl;

cout << "d_OsMsgPtr's addr of byte" ;

addr = &d_OsMsgPtr->byte[0];

cout << " byte[0] : " << addr ;

addr = &d_OsMsgPtr->byte[1];

cout << " byte[1] : " << addr ;

addr = &d_OsMsgPtr->byte[2];

cout << " byte[2] : " << addr ;

addr = &d_OsMsgPtr->byte[3];

cout << " byte[3] : " << addr << endl;

d_p = (MSG_P*) d_OsMsgPtr;

cout << "d_p : " << d_p->id << d_p->cmd << endl;

addr = &(d_p->ptr);//指向byte[3]的地址

/*****************************************************************

1,d_p->ptr本身的地址对应byte的地址,而byte中的值才是ptr指向的地址

2,而此处并不是&(d_P->ptr)并不是完全对应byte的地址,而是有两个偏移

这是由于结构体的数据对齐的原因,sizeof(MSG)是6,sizeof(MSG_P)则

是8,MSG_P的结构体里有2个byte的空缺

************ ******************* *****

*d_OsMsgPtr* ----> *id ** id ** <----*d_p*

************ *cmd ** cmd ** *****

*byte[0] ** **

*byte[1] ** **

*byte[2] **ptr **

MSG *byte[3] ** **

*********** **

** ** MSG_P

**********

指针类型转换图

**********************************************************************/

cout << "d_p addr of byte" << "the addr of &(d_p->ptr) : " << addr << endl;

//ptr的内容,即ptr指向目标地址值,此处为byte[2]和byte[3]和两个未知byte的值,

//按地址格式输出(4321)

addr = d_p->ptr; cout << "the addr of d_p->ptr : " << addr << endl;

addr = &d_p->ptr[0];//为上述ptr指向目标值,也是未知值

cout << "the addr of d_p->ptr[0] :" << addr << endl;

return 0;

//证明是由于数据对齐引起转换偏移的,可以加#pragma pack(1),使之不偏移

}

iambic 2008-06-06
  • 打赏
  • 举报
回复
运行时异常?在哪一步?
lin_style 2008-06-06
  • 打赏
  • 举报
回复
内存当然没有变化
只是读取的规则发生变化

lin_style 2008-06-06
  • 打赏
  • 举报
回复
你这么想就行了。

A{int a1;
int a2;
char a3;
int *a4;}

那么他对这段内存读取规则就是
第一个变量:0-3个字节(因为是int)
第二个变量:第4个字节(因为是char)
..
..

结构体B{
char b1;
int b2;
int b3;
char b4;}

强制转换B后,对第一个变量读取规则就是只取1个字节,这样当然就错了。。

70,037

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧