2016-06-16 64 views
1

我使用strtol來解析字符串中的整數。我打算使用strtol的第二個參數來確定整個字符串是否被解析爲一個數字。我有這樣的代碼(該字符串將不能代表< 1):可以strtol將第二個參數設置爲不在字符串中的值

char digits[32]; 
char* ptr = token->token; 
const size_t tokenLen = token->tokenLen; 

//token->token may not be NUL terminated 
//copy it to temp buffer to ensure it is 
for (size_t k = 0; k < tokenLen; k += 1) { 
    digits[k] = ptr[k]; 
} 
digits[tokenLen] = 0; 

long index = strtol(digits, &ptr, 10); 

if (
    !index || index == LONG_MAX || index >= arr->size 
    || (ptr - token->token + 1) != tokenLen 
) { 
    //Error 
} else { 
    //All good 
} 

然而,這是失敗的測試,因爲第二個參數ptr被設定爲無關我的字符串的地址。我注意到在調用之後,* ptr總是'\ 0'(我正在使用gcc-6對字符串"1"進行測試)。我發現,在strtol manpage以下文字:

特別是,如果* NPTR不是「\ 0」,但** endptr是在返回「\ 0」, 整個字符串是有效的。

我想避免簡單地檢查*ptr == '\0'因爲字符串可能包含NUL字符,這將是最好是通過在if聲明

(ptr - token->token + 1) != tokenLen 

檢查捕獲的錯誤條件。

所以我的問題是,strtol可以將第二個參數設置爲不包含在字符串中的地址,這種行爲記錄在某處?

+0

的第二個參數你'strtol'不是'ptr',但'&ptr'! – Olaf

+0

「,因爲這些字符串可能包含NUL字符」。不知道你的意思是:一個字符串*結尾*與一個NUL字符。 'may *包含*'是什麼意思? – Evert

+0

@Evert字符串是JSON指針語法的片段,它允許在語法中使用任何Unicode字符(參見[RFC 6901](https://tools.ietf.org/html/rfc6901#section-3))。所以我不依賴NUL在內存中終止的字符串,但要記住它們的長度。 – Chase

回答

2

問題是您要將字符串的副本傳遞到strtol,因此ptr的值將位於副本中,而不是原始副本。您還將長度加1,這是不正確的。只要改變:

(ptr - token->token + 1) != tokenLen 

到:

ptr - digits != tokenLen 
2

設置爲ptr的值將與作爲第一個參數傳遞的緩衝區相關,即digits。由於token->token確實點到digits陣列,下面的表達式是無效的:

(ptr - token->token + 1) 

假設tokenLen包括空終止,則需要計算

(ptr - digits) // Do not add 1 

,以便獲得的字符數由strtol消耗。

要回答你的問題,不允許strtol*ptr設置爲由第一個參數表示的字符串外部的值。

+0

這是不正確的。這裏給出的長度將會太高。 –

+0

@TomKarzes我認爲OP在他的令牌結構的'tokenLen'字段中存儲的令牌長度中包含空終止符。否則他會使用'strlen'。 – dasblinkenlight

+0

看看將它複製到'digits'的循環。它首先複製'tokenLen'字符。然後在循環之後它在'tokenLen'索引處存儲'0'。這意味着'tokenLen'不包含終止的空字節。 –

相關問題