[英]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
55
55
56
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)
為什么有效? 如果僅在較新版本的gcc
和clang
此行為,它何時開始運行,我可以在程序中依賴它嗎?
編輯:
另外,當字符串中不包含空字節時,為什么strlen()
報告一個附加字符? (在編輯中添加)
編輯:我通過找到一個空字節解決了strlen()
工作的斷言。
另外,當字符串中不包含空字節時,為什么strlen()報告一個附加字符? (在編輯中添加)
明確回答您的修改:您的假設是錯誤的。 它可能返回42
,崩潰甚至刪除您的文件。 閱讀有關未定義行為的信息,如先前的評論所建議。
報告6的技術原因是偶然的,在您的最終程序中,數組后面有2字節的0字節。 但這不能使數組成為有效的C字符串。
首先,您的函數p1
和p2
完全相同。 並非不是其中一個將字符串視為指針,而另一個將字符串視為數組。 根據定義,字符串是字符數組。 但是 ,每當我們操作數組時(尤其是將數組傳遞給函數時),我們實際使用的是指向數組第一個元素的指針。 因此,即使您的函數p2
看起來正在接收數組,它實際上仍在接收指針。 另請參閱C常見問題解答列表中的此問題 。
現在,第二,C字符串確實包含其長度的指示:所有適當的字符串都包含一個空終止符,即特殊字符'\\0'
,用於標記其結尾。 確定字符串長度的方法是通讀它,對字符進行計數,直到找到'\\0'
為止。 這正是strlen
所做的。
最后,我們來到您的數組d
。 如我所知,您已經安排好該數組看起來像字符串"Hello"
,但沒有終止的空字符。 因此,當strlen
嘗試計算d
的長度時,它將一直超出末尾,並開始檢查數組末尾是否存在任何隨機的內存區域。 可能會發生三件事:
strlen
恰好會計算出正確的答案5。 strrlen
計算出的答案可能大於5,甚至可能大於5。這就是事實。 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 char
和char array
pointer to char
行為相同。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.