免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1890 | 回复: 8
打印 上一主题 下一主题

[C] 类型转换,头疼,头疼。有两个简单问题(对我来说有点难),请教大家。 [复制链接]

论坛徽章:
1
程序设计版块每日发帖之星
日期:2015-10-21 06:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-08-31 22:52 |只看该作者 |倒序浏览
本帖最后由 moxies 于 2015-08-31 23:21 编辑

晚上好,
          有两个问题请教大家:

          1、在看<endian.h>文件时,发现他引入了另一个头文件<bits/endian.h>,后一个文件是在/usr/include/i386-linux-gnu下,请问是在哪里指定的i386-linux-gnu这个路径的? (grep -R -n i386-linux-gnu /usr/include 无果)。

          2、uint16_t bt_get_unaligned 相关,先上测试代码:
  1. #include <bluetooth/bluetooth.h>
  2. #include "hci.h"
  3. #include "mgmt.h"
  4. #include <inttypes.h>

  5. int main(){
  6.         printf("result: %d\n",1&1<<1);
  7.         char  buf[] = {0x04,0x04,0x0a,0x2e,0xe7,0xde,0x3d,0x1e,0x00,0x00,0x1f,0x00,0x01};
  8.         struct mgmt_hdr *hdr = (void *)buf;

  9.         printf("%s\n",(char*)&hdr->opcode); //这里实在不知道改怎么写了。想先把原始值打出来,和转换后的做对比。

  10.         uint16_t code = btohs(bt_get_unaligned(&hdr->opcode));
  11.         if(code == 0x000B){
  12.                 printf("ok\n");
  13.         }
  14.         printf("result is : %" PRIu16 "\n",code);
  15.         return 0;
  16. }
复制代码
输出是:result is : 1028

        这是bluez的代码:
  1. opcode = btohs(bt_get_unaligned(&hdr->opcode));
  2.         len = btohs(bt_get_unaligned(&hdr->len));
  3.         index = btohs(bt_get_unaligned(&hdr->index));

  4.         if (ret != MGMT_HDR_SIZE + len) {
  5.                 error("Packet length mismatch. ret %zd len %u", ret, len);
  6.                 return TRUE;
  7.         }

  8.         switch (opcode) {
  9.         case MGMT_EV_CMD_COMPLETE:
  10.                 mgmt_cmd_complete(sk, index, buf + MGMT_HDR_SIZE, len);
  11.                 break;
  12. 。。。。
复制代码
补充下bt_get_unaligned宏:
  1. #define bt_get_unaligned(ptr)                        \
  2. ({                                                \
  3.         struct __attribute__((packed)) {        \
  4.                 __typeof__(*(ptr)) __v;                \
  5.         } *__p = (__typeof__(__p)) (ptr);        \
  6.         __p->__v;                                \
  7. })
复制代码
跟踪bluez日志发现bluez 走的是MGMT_EV_DEVICE_CONNECTED(0x000B)分支。
        这里就抓狂了。测试中的code 和 bluez的opcode 对不上了。很不解。也许printf的问题。还请大神帮忙讲讲bt_get_unaligned这个宏。为什么要这么做。谢谢。

论坛徽章:
1
程序设计版块每日发帖之星
日期:2015-10-21 06:20:00
2 [报告]
发表于 2015-08-31 23:09 |只看该作者
@windoze 看你在,帮说说看吧。 哎。。。闹不清楚不想睡觉了都。。

论坛徽章:
1
程序设计版块每日发帖之星
日期:2015-10-21 06:20:00
3 [报告]
发表于 2015-08-31 23:17 |只看该作者
路过的兄弟门,别光看啊。有想法的来讲讲。也许我测试的数据不对。但真的想知道那个宏的作用。猜测都可以。要留下你的脚印啊。否则这个帖子太孤独了。

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
4 [报告]
发表于 2015-08-31 23:25 |只看该作者
本帖最后由 windoze 于 2015-08-31 23:25 编辑

第一个问题,include这玩意儿是cpp负责的,所以可以用
  1. cpp -v
复制代码
看到所有缺省的include path,不出意外应该能看到/usr/include/i386-linux-gnu,不过我的Arch里endian.h是在/usr/include/bits下面。

第二个问题还没看,等下有空了再说

论坛徽章:
1
程序设计版块每日发帖之星
日期:2015-10-21 06:20:00
5 [报告]
发表于 2015-08-31 23:38 |只看该作者
本帖最后由 moxies 于 2015-08-31 23:38 编辑

回复 4# windoze


1 第一个问题的追问:如果是app的include_path决定,那么在bits下的endian 和 /usr/include下endian 并没有做 头文件重复导入定义的判断,怎么能保证先加载/usr/include下的endian呢?


2 一定要看啊。谢谢了先。呵呵

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
6 [报告]
发表于 2015-08-31 23:41 |只看该作者
回复 5# moxies

我看到bits/endian.h里面写着
Never use <bits/endian.h> directly; include <endian.h> instead.


而endian.h里面分明有

  1. #ifndef _ENDIAN_H
  2. #define _ENDIAN_H        1
  3. ...
  4. #endif        /* endian.h */
复制代码
只不过最开头一段都是版权声明,你可能没看清。

论坛徽章:
1
程序设计版块每日发帖之星
日期:2015-10-21 06:20:00
7 [报告]
发表于 2015-08-31 23:48 |只看该作者
哦。我粗心了。第一个问题解决了。早点休息吧。明天如果有空,帮我看看第二个问题。很感谢。
   

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
8 [报告]
发表于 2015-08-31 23:52 |只看该作者
bt_get_unaligned(ptr)看起来根据ptr指向的类型定义了一个新的类型。
这个新类型有__attribute__((packed))属性,目的就是把原有类型里末尾的padding干掉,所以才起这个名字吧。
比如

  1. // 这个类型是4字节对齐的,因为里面有一个int成员,所以其实后面有3个字节的padding
  2. struct S {
  3.   int n;
  4.   char c;
  5. };
  6. S *ptr;
  7. bt_get_unaligned(ptr);
  8. // 上面那个宏相当于定义了一个新的unaligned S,1字节对齐
  9. struct  __attribute__((packed))  unaligned_S_wrapper {
  10.    struct S v;
  11. } *__p=(unaligned_S *)(ptr);
  12. // 这里v就变成1字节对齐的了,因为外面的wrapper有packed属性
复制代码
估计这个宏是用来做I/O的,因为原有的S后面有3个字节完全没用的东西,用这个宏搞一下就把这3个字节干掉了。

论坛徽章:
1
程序设计版块每日发帖之星
日期:2015-10-21 06:20:00
9 [报告]
发表于 2015-09-01 06:59 |只看该作者
回复 8# windoze



    呵呵,我这个提问者,还真是懒,居然比你下线的早。真是该罚。 总之,谢谢你。 刚突然想到,是否可用用二进制观察下。数据的变化,比对起来可能就直观了。我再想想代码怎么写。


   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP