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型。

  • 相关阅读:
    socket 编程
    空间配置器
    线程
    Linux系统编程——进程替换:exec 函数族
    linux粘着位
    exit函数与_exit
    [smart210] 定时器与PWM
    [smart210] s5pv210的中断体系
    [smart210] Nand Flash K9F4G08U0B 的配置与读写控制(二)
    [smart210] Nand Flash K9F4G08U0B 的配置与读写控制(一)
  • 原文地址:https://www.cnblogs.com/fogcell/p/6714294.html
Copyright © 2011-2022 走看看