2014-01-24 164 views
4

我正在研究從bsd的libc函數strtok的代碼,當我在我的機器上運行它時, 程序收到信號SIGSEGVs[-1] = 0。 代碼如下是links [-1] = 0是什麼意思?

s[-1] = 0對不對?

這是我的代碼:

#include <stdio.h> 
#include <stdlib.h> 
#include "strtok.c" 

int main(int argc, char* argv[]) { 
    char* str = "xxxx xxxyy fdffd"; 
    const char* s = " "; 

    char* token = strtok(str, s); 

    while (token != NULL) { 
     printf("%s\n", token); 
     token = strtok(NULL, s); 
    } 

    return 0; 
} 
+2

是的,沒錯。但是,您的調用代碼可能不是。 –

+2

可能'[-1] = 0'是正確的。可能調用它的代碼是錯誤的。 –

+1

http://www.codinghorror.com/blog/2008/03/the-first-rule-of-programming-its-always-your-fault.html –

回答

6
s[-1] 

被擴展爲:

*(s - 1) 

因此,如果結果指向有效的存儲器,所述代碼被定義。

+2

(-1)[s]將同樣有效。瘋狂! –

+0

它有助於記住C不*真*有數組,只是指針。 –

+2

@HotLicks C肯定有數組。 http://eli.thegreenplace.net/2009/10/21/are-pointers-and-arrays-equivalent-in-c/對數組做[[]]是未定義的b。 – this

1

它應該是OK事業幾行上面確實小號++,所以最壞的情況下,我們正在與(S + 1)-1。

3

這是可以的,因爲s是我們可以從C99標準草案看指針E1[E2] is identical to (*((E1)+(E2)))從部分6.5.2.1數組下標說(重點煤礦):

後綴表達式後跟表達式在方括號[]中是下標 指定數組對象的元素。下標運算符[] 的定義是E1 [E2]與(*((E1)+(E2)))相同。由於 適用於二元運算符的轉換規則,如果E1是一個數組對象(等價地,指向數組對象的初始元素的指針)並且E2是一個整數,則E1 [E2]指定第E2個E1的元素(從零開始計數)。

如果s是一個數組,但這不會是有效的代碼,因爲我們將訪問不屬於該數組的內存,這將是未定義的行爲。

1

無論s[-1] = 0是「正確」或「錯誤」將取決於s運行時間值。

s[-1] = 0本身沒有什麼內在錯誤或不尋常的。

3

s[-1]指的是之前的對象s指向的對象。根據C的規則,s[-1]相當於*(s-1)。這個:

  • 計算s-1。結果是指向s指向的對象之前的對象的指針,s+1是指向s之後的對象的指針的相同方式。
  • 推斷它,它產生指向對象的左值。

因此,s[-1] = 0將0指定給s指向的對象之前的對象。

s[-1]是合法代碼,如果s指向第一個元素之後的數組元素(因此確保它之前有一個元素)或s指向數組的末尾。 (這也是合法的,如果s指向一個超出單個對象的數組,這是非常不尋常的用途。)

0

只是一個預感,但我相當肯定FreeBSD的strtok(3)是相當穩定的,相當不錯的測試。

schar*; s[-1]s指向的那個字符設置爲NUL

我們可以看到您的實際代碼是strtok(3)嗎?這個問題可能在你的設置中,可以這麼說。此外,您是否閱讀過手冊頁?

第一次調用strtok()時,應該指定str;後續調用,希望從同一個字符串中獲得更多的標記, 應該傳遞一個空指針。必須每次提供分隔符字符串sep, ,並且可能會在兩次調用之間進行更改。