2012-07-24 33 views
2

我試圖在32位機器上執行十六進制到整數的轉換。這裏是我與測試代碼,將十六進制字符串轉換爲長

int main(int argc,char **argv) 
{ 
    char *hexstring = "0xffff1234"; 
    long int n; 

    fprintf(stdout, "Conversion results of string: %s\n", hexstring); 
    n = strtol(hexstring, (char**)0, 0); /* same as base = 16 */ 
    fprintf(stdout, "strtol = %ld\n", n); 
    n = sscanf(hexstring, "%x", &n); 
    fprintf(stdout, "sscanf = %ld\n", n); 
    n = atol(hexstring); 
    fprintf(stdout, "atol = %ld\n", n); 
    fgetc(stdin); 

    return 0; 
    } 

這是我得到什麼:

strtol = 2147483647 /* = 0x7fffffff -> overflow!! */ 
sscanf = 1 /* nevermind */ 
atol = 0 /* nevermind */ 

正如你看到的,與strtol將我得到的溢出(我還檢查與錯誤號),但我會預計不會發生,因爲0xffff1234是一個有效的整數32位值。 我會期望4294906420或其他-60876

我錯過了什麼?

+0

你確定設置基數爲0是16。我的意思是替換* strtol(hexstring,(char **)0,0)* * strtol(hexstring,(char **)0,* * 16 **)* – 2012-07-24 09:48:16

+0

@AG設置基數爲0意味着'strtol'試圖從輸入字符串的開頭找出它自己,無論是使用16,10或8的數字。 – 2012-07-24 10:14:42

+0

對,我忘了!謝謝 ! – 2012-07-24 13:11:41

回答

6

如果您不想要溢出效果,請不要使用該函數的已簽名變體。改爲使用strtoul()

用下面的代碼:

#include <stdio.h> 
int main(int argc,char **argv) { 
    char *hexstring = "0xffff1234"; 
    long sn; 
    unsigned long un; 

    fprintf(stdout, "Conversion results of string: %s\n", hexstring); 

    sn = strtoul(hexstring, (char**)0, 0); 
    fprintf(stdout, "strtoul signed = %ld\n", sn); 

    un = strtoul(hexstring, (char**)0, 0); 
    fprintf(stdout, "strtoul unsigned = %lu\n", un); 

    return 0; 
} 

我得到:

Conversion results of string: 0xffff1234 
strtoul signed = -60876 
strtoul unsigned = 4294906420 

調用strtol()及其弟兄,因爲行爲是這些功能時,您無法控制這一點。標準有這樣的說法:

strtol,strtoll,strtoul和strtoull函數返回轉換後的值,如果有的話。如果不能執行轉換,則返回零。如果正確值超出了可表示值的範圍,則返回LONG_MIN,LONG_MAX,LLONG_MIN,LLONG_MAX,ULONG_MAX或ULLONG_MAX(根據返回類型和值的符號(如果有)),並且宏ERANGE的值爲存儲在errno中。

+0

這是正確的解決方案,沒關係。呃,我在文檔前面看到了它,但沒有看到它:無論如何D + 1。 :) – ATaylor 2012-07-24 09:51:18

+0

@juampa我相信功能內發生溢出。爲什麼還會有兩個功能?但是,如果你輸出'n'的內容爲有符號的,你會得到-60876 ... meh,他的編輯擊敗了我:D – ATaylor 2012-07-24 09:52:43

3

long最小範圍爲-2147483647到2147483647的long您的實施範圍很可能-2147483648到2147483647

strtol()的定義說,如果轉換值超出範圍long,LONG_MINLONG_MAX根據轉換值的符號返回,並且ERANGE存儲在errno中。在這種情況下,轉換後的值0xffff1234超出範圍 - 大於LONG_MAX,因此返回LONG_MAX

順便說一句,你的sscanf()呼叫在nsscanf()的返回值,這是1,表明有1個轉換成功覆蓋換算值。

相關問題