打印

类型转换问题请教!

[复制链接]
1692|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lyf9908|  楼主 | 2014-8-26 15:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
hd, hdr, ev, os, ST
下面是BLE协议中摘录整理的代码;
现有如下的两个结构定义:
typedef struct
{
   void   *next;
   uint16 len;
   uint8  dest_id;
} osal_msg_hdr_t;

typedef struct
{
   uint8  event;
   uint8  status;
} osal_event_hdr_t;

osal_msg_hdr_t *foundHdr = listHdr;// 此处定义了一个指针变量并赋值,所以foundHdr指向内存中一个                     
                    osal_msg_hdr_t型的结构体变量;

osal_event_hdr_t *pMsg = (osal_event_hdr_t *)foundHdr //此处把foundHdr类型转换后赋给变量pMsg
                            本质上pMsg还是指向上面定义的  
                            osal_msg_hdr_t型的结构体变量;

if (pMsg->event == HCI_GAP_EVENT_EVENT)    //此处引用pMsg->event,其在内存中的位置应                           
                           该就是osal_msg_hdr_t结构体变量的
                           void   *next它存储的是一个指向消息头的指针
{
   ......
}

此处foundHdr先被定义为sal_msg_hdr_t型的指针变量,并给其赋初值,其指向一个osal_msg_hdr_t型的结构体变量
接着把foundHdr转换成osal_event_hdr_t 型的指针后赋给pMsg,所以本质上而言,pMsg在内存中还是指向osal_msg_hdr_t型的结构体变量
接着使用pMsg->event,所以此时的pMsg->event按在内存中的位置而言,应该就是osal_msg_hdr_t变量的void   *next; void   *next处应为一个消息头的指针,与event没有关系,而此时直接使用if (pMsg->event ==  HCI_GAP_EVENT_EVENT),能这样用吗?会不会有问题; 

相关帖子

沙发
hgjinwei| | 2014-8-26 20:32 | 只看该作者
这不单单是自找麻烦,还把源码搞得非一般的乱。

使用特权

评论回复
板凳
dictionary| | 2014-8-26 20:50 | 只看该作者
没见过这么用的,void只是个地址,又不是事件 你确定 你没漏掉什么?

使用特权

评论回复
地板
zhusizhan| | 2014-8-27 09:37 | 只看该作者
对于C语言的指针类型转换问题
我认为可以简单理解成, 指针(无论类型)就是指向某个地址, 关键在于该指针有效范围是多少,
也就是指针的类型了.
例如: void * pvoid = 0x100000, 和 unsigned int * puint = 0x10000000,
它们都指向0x10000000地址, 但pvoid不知道有效范围, 也就是不知道应该什么时候结束, puint知道
有效范围(4个字节).
又例如:  一般void *用作回调函数的形参比较多, 为了回调函数的通用性, 其实在调用
回调函数时你要传递的就是一个地址, 并不是整个数据(甚至结构体), 所以不必在调用时
就知晓指针的有效范围, 在执行回调函数时知道有效范围就可以了.
下面就看看你的问题, osal_msg_hdr_t结构体的第一个成员是void*, 从字面上看只知道它是指向
某个地址, 不知道范围, 从下面的代码可以看出第一个成员其实就是指向osal_event_hdr_t结构体,
那么这就不难理解后续代码对指针的转换了, 转换仅仅是为了告知你(程序员)指针的范围.

使用特权

评论回复
5
lyf9908|  楼主 | 2014-8-27 10:52 | 只看该作者
感谢zhusizhan的回答,很精辟:))
   也就是说,
         osal_event_hdr_t *pMsg = (osal_event_hdr_t *)foundHdr
        上边的语句中,当 (osal_event_hdr_t *)foundHdr类型转换时,编译时就在 
        osal_msg_hdr_t结构体中的 void   *next处写入了osal_event_hdr_t结构体地首地址;
   但是,如果是这样的话,if语句是不是应该这样写?
                  if (pMsg->next->event == HCI_GAP_EVENT_EVENT)
   
  

使用特权

评论回复
6
zhusizhan| | 2014-8-27 17:58 | 只看该作者
lyf9908 发表于 2014-8-27 10:52
感谢zhusizhan的回答,很精辟:))
   也就是说,
         osal_event_hdr_t *pMsg = (osal_e ...

不是编译态, 是运行态
next是void类型, 如果if写成那样, 编译通不过, 必须做类型转换

使用特权

评论回复
7
dirtwillfly| | 2014-8-27 22:11 | 只看该作者
四楼说的对啊
void类型的变量,比较蛋痛

使用特权

评论回复
8
wangflw| | 2014-9-3 16:32 | 只看该作者
osal_event_hdr_t *pMsg = (osal_event_hdr_t *)foundHdr

这句转换是处于什么道理呢?虽说没有错误,但是后面pMsg 的引用会出在问题的。
if (pMsg->event == HCI_GAP_EVENT_EVENT)
这里的even成员值确定没有问题?

使用特权

评论回复
9
zhusizhan| | 2014-9-4 08:16 | 只看该作者
wangflw 发表于 2014-9-3 16:32
这句转换是处于什么道理呢?虽说没有错误,但是后面pMsg 的引用会出在问题的。
if (pMsg->event == HCI_GA ...

怎么会出问题呢?
因为pMsg指向了foundHdr指向的地址, 它们指向的地址中的内存区存放的是osal_event_hdr_t数据.
类型转换的正确与否, 不在于结构体本身, 而在于指向的内存数据.

使用特权

评论回复
10
wangflw| | 2014-9-5 13:09 | 只看该作者
类型转换的正确与否, 不在于结构体本身, 而在于指向的内存数据.

这句话一点也没错。指针强制类型转换的时候是不会有错。但是你强制转换之后,使用指针进行数据引用的时候,如果原本的数据结构和强制转换的数据结构不一致,引用到的数据没有意义啊!
代码中:
osal_msg_hdr_t *foundHdr = listHdr;
osal_event_hdr_t *pMsg = (osal_event_hdr_t *)foundHdr;
if (pMsg->event == HCI_GAP_EVENT_EVENT)
关键是listHdr是什么类型的数据。最终引用的是listHdr里面的数据啊。如果listHdr是osal_event_hdr_t型,那没问题。但如果是osal_msg_hdr_t,引用真的没问题吗?数据存储的结构都不一样,引用到的数据没有意义。

使用特权

评论回复
11
lyf9908|  楼主 | 2014-9-24 15:44 | 只看该作者
各位,是我搞错了!
  仔细的检查后发现问题出在listHdr, listHdr在内存中指向一个结构体变量:typedef struct
                                       {
                                           osal_event_hdr_t  hdr;
                                              uint8             state;  // shift
                                              uint8             keys;   // keys
                                       } keyChange_t;
   又有如下定义:

  typedef struct
      {
         uint8  event;
        uint8  status;
      } osal_event_hdr_t;

使用特权

评论回复
12
lyf9908|  楼主 | 2014-9-24 15:46 | 只看该作者
所以,pMsg->event 实际上就是结构体变时osal_event_hdr_t的成员event;
        这样一来就没有问题了;

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

133

主题

176

帖子

0

粉丝