zoukankan      html  css  js  c++  java
  • 关于char型与unsigned char型数据使用格式化输出注意点

      在使用 socket(AF_INET, SOCK_DGRAM, 0); 打开一个套接字流,通过 ioctl(s, SIOCGIFHWADDR, &ifr) 获取网卡的mac地址的时候,需要将 struct ifreq ifr; 结构体中 ifr.ifr_hwaddr.sa_data 数组中的信息按照十六进制提取到字符串中去,程序中使用到了

    sprintf(mac, "%02X:%02X:%02X:%02X:%02X:%02X", 
                ifreq.ifr_hwaddr.sa_data[0],
                ifreq.ifr_hwaddr.sa_data[1],
                ifreq.ifr_hwaddr.sa_data[2],
                ifreq.ifr_hwaddr.sa_data[3],
                ifreq.ifr_hwaddr.sa_data[4],
                ifreq.ifr_hwaddr.sa_data[5]);

      提取到mac中,但是原本Mac地址为 48:4d:7e:b1:e2:7e 存在结果字符输出 48:4D:7E:FFFFFFB1:FFFFFFE2:7E 。这明显不正常,如果使用如下的方式获取则没有问题

    unsigned char mac[6];
    memcpy(mac, ifr.ifr_hwaddr.sa_data, sizeof(mac)); sprintf(buffer, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);

      当时考虑到是否是因为不同Linux内核中的结构体 struct ifreq ifr; 中存在差异才导致问题,后来查找到.ifr_hwaddr.sa_data原型为char sa_data[14]。经过相关搜索,问题的原因如下:

      有符号char型的数值范围是-128-127因此大于0x7F的数在char型下其符号位则为1,因此当以%X格式化输出的时候,会把这个类型的值拓展,通常拓展到int型的32位,那么会对char类型的最高位进行拓展,%x期望的数据类型应该是unsigned int型,因此char转换到unsigned int也会拓展符号位,也就是强制类型转换了。

      当为char类型的时候,如果最高位是1,意思是超过了0x7F的数则会被拓展为32位的FFFFFFB1。所以会出现这种情况。但是第二种方法则是直接指定从指针指向的值提取,因此不会出现这种带有符号位的情况。即,使用%x格式化输出的时候,一般char数据会被拓展到int型大小,一般为32位。

      可以通过(unsigned char)ifreq.ifr_hwaddr.sa_data[5]来解决问题。使用%x输出格式的时候需要将所需要的数据转换为无符号类型,因为%x期望对应的参数应该为unsigned int型。

  • 相关阅读:
    PHP读取XML数据中CDATA内数值
    微信支付报ip错,怀疑是因为不能正确获取$_Server[addr])ip导致的
    微信支付错误两个问题的解决:curl出错,错误码:60
    tp框架 验证码的应用注意事项
    PHP结合jQuery.autocomplete插件实现输入自动完成提示的功能
    mysql存储小数
    windows服务器剪贴板不能共用的解决办法
    网页设为首页和添加收藏
    网页qq客服代码并自定义图片
    windows apache开启url rewrite
  • 原文地址:https://www.cnblogs.com/fogcell/p/6714294.html
Copyright © 2011-2022 走看看