printf、sscanf进行16进制数据转换问题

问题1:原程序的目的是将字符串形式的mac地址存放在char型数组当中(如有更好的获取方法留言说下,谢谢),代码如下,在mac执行如下代码后,变量int型值发生了变化。

#include 

typedef unsigned int uint32;

int main(void)
{
    int num = 1;
    char str_mac[] = "7f:ab:ee:af:55:76";
    unsigned char mac[6] = {0};

    printf("num = %d\n", num);

    sscanf((char *)str_mac, "%2x:%2x:%2x:%2x:%2x:%2x", (uint32 *)&mac[0],(uint32 *)&mac[1],(uint32 *)&mac[2],(uint32 *)&mac[3],(uint32 *)&mac[4],(uint32 *)&mac[5]);

    printf("&mac[5] = %p; &num = %p\n", &mac[5], &num);
    printf("num = %d\n", num);

    printf("mac : [%x:%x:%x:%x:%x:%x]\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 

    return 0;
}
运行结果如下:
➜  sscanf  ./a.out 
num = 1
&mac[5] = 0x7fff586b6897; &num = 0x7fff586b6898
num = 0
mac : [7f:ab:ee:af:55:76]

原因是%x匹配unsigned int型指针,在对mac[5]地址进行赋值操作的时候,是对mac[5]为起始的四个字节进行了赋值操作,影响到了变量i的值。

修改后的代码如下(如有更好的方法,留言说下,谢谢):
int main(void)
{
    int num = 1;
    char str_mac[] = "7f:ab:ee:af:55:76";
    unsigned int tmp_mac[6] = {0};
    unsigned char mac[6] = {0};
    int i = 0;

    printf("num = %d\n", num);

    sscanf((char *)str_mac, "%2x:%2x:%2x:%2x:%2x:%2x", (uint32 *)&tmp_mac[0],(uint32 *)&tmp_mac[1],(uint32 *)&tmp_mac[2],(uint32 *)&tmp_mac[3],(uint32 *)&tmp_mac[4],(uint32 *)&tmp_mac[5]);

    for (i = 0; i < sizeof(mac); i++)
    {   
        mac[i] = tmp_mac[i]; 
    }   

    printf("num = %d\n", num);
    printf("mac : [%x:%x:%x:%x:%x:%x]\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);

    return 0;
}


问题2: 执行如下程序:
#include 

int main(void)
{
    char a = 0xbf;
    printf("char_a = %2x \n", a); 

    unsigned char ua = 0xbf;
    printf("unsigned_char_a = %2x \n", ua);

    char b = 0x7f;
    printf("char_b = %2x \n", b); 

    int c = 0xbf;
    printf("int_c = %2x \n", c); 

    int d = 0x7f;
    printf("int_d  = %2x \n", d); 
    return 0;
}
运行结果如下:
➜  hex  ./a.out 
char_a = ffffffbf 
unsigned_char_a = bf 
char_b = 7f 
int_c = bf 
int_d  = 7f 

为什么char_a打印的值前面多了ffffff,其它的都是想要的打印值。
原因是没有注意变量类型的取值范围!
char 型变量的取值范围是 (-128,127);而0xbf的值是191,超出了其范围大小,实际对应的十进制数值是-65,负数在计算机中以补码的形式存储。
printf所要求的输出格式是%x,其对应的变量类型是unsigned int,所以-65以unsigned int类型来进行解读。
-65在计算机中的表示方式转化如下:
1、0000 0000 0000 0000 0000 0000 0100 0001 先进行取反 1111 1111 1111 1111 1111 1111 1011 1110
2、在上面转化的基础上加1后得 1111 1111 1111 1111 1111 1011 1111,这个就是在计算机中的存储形式
3、将上面计算机中的存储形式按unsigned int进行解读得到的值就是 ffffffbf

参考链接:
http://www.ruanyifeng.com/blog/2009/08/twos_complement.html

你可能感兴趣的:(C编程语言)