1. 程式人生 > >printf、sscanf進行16進位制資料轉換問題

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