2015-08-19 64 views
2

我的strtol函數在溢出轉換期間未能設置errno。Strtol在溢出轉換時未設置errno

#include <stdio.h> 
#include <string.h> 
#include <malloc.h> 
#include <getopt.h> 
#include <errno.h> 
#include <stdlib.h>  

int main(int argc, char **argv) { 

    errno = 0; 
    int e = strtol("1000000000000000", NULL, 10); 
    printf("%d %d\n", errno, e); 

    return 0; 
} 

回報

0 -1530494976 

我該怎麼辦錯了嗎?

編譯

gcc (Ubuntu 4.9.2-10ubuntu13) 4.9.2 

選項

gcc -Wall -std=gnu99 -O2 
+2

你使用什麼編譯器(及其版本)?你有沒有包含所有必要的標題? –

+0

手冊頁說什麼是'strol'的返回類型? – kaylum

+0

好吧,編譯器和頭文件增加 – Krzysztofik

回答

5

沒有什麼錯的strtol()實施,但有一個與你的代碼。

該函數的返回類型是long(參見後l)和明顯的值1000000000000000可由long整數類型來表示。但返回值分配給e,其類型爲int,無法表示此值。然後發生的是實現定義。

因此將int e更改爲long e"%d %d\n""%d %ld\n"。如果你想保持它作爲int,那麼你必須檢查值是它的範圍表示的值以外的自己:

#include <stdio.h> 
#include <errno.h> 
#include <stdlib.h> 
#include <limits.h> // for INT_{MIN,MAX} 
int 
main(void) 
{ 
    errno = 0; 
    long f = strtol("1000000000000000", NULL, 10); 
    if (errno == ERANGE) { 
     puts("value not representable by long (or int)"); 
    } else if (f < INT_MIN || f > INT_MAX) { 
     puts("value not representable by int"); 
    } else { 
     int e = f; 
     printf("%d\n", e); 
    } 
} 
+0

感謝您的回答。你可能知道是否有一個正常的int轉換功能,溢出檢測? – Krzysztofik

+0

@Krzysztofik:我已經添加了一個例子。 – cremno

+0

@cremno其實,這是一個大腦放屁。你是對的,這是LP64,而不是LLP64。 – Sneftel

0

你做得很好,但你不檢查strtolerrno值,但爲printf() ....不明白讓我解釋一下... long f = strtol("1000000000000000", NULL, 10);之後聲明你必須先保存errno的值。因爲在此聲明之後,您將打電話給printf()聲明,該聲明也相應地設置了errno

printf("errno is: %d\n", errno); 

所以在這個聲明中「錯誤號」給出printf()不是strtol()錯誤指示......這樣做節省「錯誤號」調用任何庫函數之前,因爲大多數的庫函數與「錯誤號」進行互動。 正確的使用方法是:

long f = strtol("1000000000000000", NULL, 10); 
int saved_error = errno;  // Saving the error... 
printf("errno is: %d\n", saved_error); 

現在檢查。它會給出正確的輸出肯定...還有一件事將這errno轉換爲一些有意義的字符串來表示錯誤。使用strerror()功能爲:

printf("Error is: %s\n", strerror(saved_error)); 

Cremno's answer是正確的,但這個是比較通用的。