printf、sscanf進行16進制數據轉換問題

問題1:原程序的目的是將字符串形式的mac地址存放在char型數組當中(如有更好的獲取方法留言說下,謝謝),代碼如下,在mac執行如下代碼後,變量int型值發生了變化。

#include <stdio.h>

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 <stdio.h>

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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章