簡體   English   中英

strlen()如何計算當前函數中未定義的字符串的長度?

[英]How does strlen() calculate the length of a string not defined in the current function?

據我了解,在C數組和指向字符串的指針中沒有隱式包含有關相應數組中元素數量的信息。 這就是為什么除了argv之外,還必須將argc傳遞給main() 但是,在我的機器上,即使未在與printf()相同的作用域中定義字符串,以下代碼也可以正確打印字符串"Hello"的長度,即5

#include <stdio.h>
#include <string.h>

void p1(char *a)
{
    printf("%lu\n", strlen(a));
}

void p2(char a[])
{
    printf("%lu\n", strlen(a));
}

int main(int argc, char *argv[])
{
    char *a = "Hello";
    char b[] = "Hello";
    char c[] = {'H', 'e', 'l', 'l', 'o', '\0'};
    char d[] = {'H', 'e', 'l', 'l', 'o'};

    p1(a);
    p2(a);

    printf("\n");

    p1(b);
    p2(b);

    printf("\n");

    p1(c);
    p2(c);

    printf("\n");

    p1(d);
    p2(d);

    return 0;
}

這是我的結果和機器類型:

$ ./每年
5
5

5
5

5
5

6
6

$ uname -a
Linux厭惡3.16.0-37-generic#51-Ubuntu SMP Tue May 5 5 13:45:59 UTC 2015 x86_64 x86_64 x86_64 GNU / Linux

$ cat / etc / issue
Ubuntu 14.10 \\ n \\ l

strlen()如何確定字符串長度? 即使將字符串顯式發送為指針(例如在函數調用函數p1(a)為什么有效? 如果僅在較新版本的gccclang此行為,它何時開始運行,我可以在程序中依賴它嗎?


編輯:

另外,當字符串中不包含空字節時,為什么strlen()報告一個附加字符? (在編輯中添加)

編輯:我通過找到一個空字節解決了strlen()工作的斷言。

strlen()如何確定字符串長度?

strlen()搜索終止的null'\\0' ),並從頭(指針)開始計算字符(即字節數),直到null為止,但不包括null本身。

請記住, C風格的字符串定義為以空值結尾。

請注意,由於strlen()的返回類型為size_t ,因此應使用%zu格式說明符來打印返回值。


編輯:

如果char數組不是以null結尾的, 則不符合被稱為string的條件 在任何與字符串相關的庫函數中使用這種數組,無疑會調用未定義的行為

有關更多信息,請檢查手冊頁中的strlen()

只需閱讀標准。 它清楚地定義了strlen 工作 您的主張是錯誤的。

當與字符串函數一起使用時,您的char數組 d調用未定義的行為 (最后一句話)。

另外,當字符串中不包含空字節時,為什么strlen()報告一個附加字符? (在編輯中添加)

明確回答您的修改:您的假設是錯誤的。 它可能返回42 ,崩潰甚至刪除您的文件。 閱讀有關未定義行為的信息,如先前的評論所建議。

報告6的技術原因是偶然的,在您的最終程序中,數組后面有2字節的0字節。 但這不能使數組成為有效的C字符串。

首先,您的函數p1p2完全相同。 並非不是其中一個將字符串視為指針,而另一個將字符串視為數組。 根據定義,字符串是字符數組。 但是 ,每當我們操作數組時(尤其是將數組傳遞給函數時),我們實際使用的是指向數組第一個元素的指針。 因此,即使您的函數p2看起來正在接收數組,它實際上仍在接收指針。 另請參閱C常見問題解答列表中的此問題

現在,第二,C字符串確實包含其長度的指示:所有適當的字符串都包含一個空終止符,即特殊字符'\\0' ,用於標記其結尾。 確定字符串長度的方法是通讀它,對字符進行計數,直到找到'\\0'為止。 這正是strlen所做的。

最后,我們來到您的數組d 如我所知,您已經安排好該數組看起來像字符串"Hello" ,但沒有終止的空字符。 因此,當strlen嘗試計算d的長度時,它將一直超出末尾,並開始檢查數組末尾是否存在任何隨機的內存區域。 可能會發生三件事:

  • 緊接該數組之后,內存中的下一件事可能恰好是一個0字節。 在這種情況下,很偶然地, strlen恰好會計算出正確的答案5。
  • 數組后面的內存中可能還有其他一些隨機字節,並且其中某些位置是0字節。 在這種情況下, strrlen計算出的答案可能大於5,甚至可能大於5。這就是事實。
  • 找到0字節之前, strlen可能會運行到分配給您的進程的內存末尾,在這種情況下,您會收到一些操作系統級別的錯誤消息,例如分段沖突或總線錯誤,或者“此程序意外終止”或“死亡藍屏”。

strlen的實現

size_t strlen(const char * str) {
    const char * s;
    for (s = str; *s; ++s);
    return(s - str);
}

循環終止條件*s在內部為*s != '\\0' 因此,它一直循環直到找到終止null字符。 並且, pointer to charchar array pointer to char行為相同。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM