這裏沒有什麼特別的asm;這與C中的問題是一樣的。關於如何將字符串存儲在內存中並跟蹤它們結束的位置。
以空結尾的字符串和不以null結尾的字符串之間有什麼不同?
一個空結束的字符串有後一個0
字節,所以你可以找到與strlen
結束。 (或rep scasb
)。這可以用作隱式長度字符串,就像C用法一樣。
它們是可以互換的嗎?
如果您知道空終止字符串的長度,您可以將指針+長度傳遞給需要顯式長度字符串的函數。該函數永遠不會查看0
字節,因爲您將傳遞一個不包含0
字節的長度。這不是字符串數據的一部分。
但是,如果你有一個沒有終結符的字符串,你不能將它傳遞給一個函數或系統調用,它需要一個以空字符結尾的字符串。 (如果內存是可寫的,你可以在字符串後存儲0
,使之變成一個空結尾的字符串。)
在Linux中,許多系統調用需要字符串作爲C風格的隱含長度空值終止字符串。 (即只是一個char*
而不通過一段長度)。
例如,open(2)
需要一個字符串作爲路徑:int open(const char *pathname, int flags);
您必須將一個以空字符結尾的字符串傳遞給系統調用。在Linux中創建一個名稱包含'\0'
的文件是不可能的(與其他大多數Unix系統一樣),因爲處理文件的所有系統調用都使用以空字符結尾的字符串。
OTOH,write(2)
需要一個內存緩衝區,它不一定是一個字符串。它有簽名ssize_t write(int fd, const void *buf, size_t count);
。它不關心在buf+count
有0
,因爲它只查看從buf
到buf+count-1
的字節。
您可以將字符串傳遞給write()
。它不關心。它基本上只是內核頁面緩存的一個memcpy(或者到一個管道緩衝區或任何非常規文件)。但就像我說的,你不能通過一個任意的非終止緩衝區作爲路徑參數爲open()
。
或者它們並不相等?
隱式長度和顯式長度是跟蹤內存中字符串數據/常量並傳遞它們的兩種主要方式。他們解決同樣的問題,但方式相反。
如果您有時需要在穿過它們之前找到它們的長度,那麼長的隱式長度字符串是一個不錯的選擇。通過字符串循環比讀取整數要慢很多。查找隱式長度字符串的長度爲O(n)
,但顯式長度的字符串當然是O(1)
時間來查找長度。 (這是已知的!)。至少以字節爲單位的長度是已知的,但如果使用UTF-8或UTF-16等可變長度編碼,則Unicode字符的長度可能不知道。
如何獲得'greeting2'的長度?使用'greeting1',您可以查找第一個空字節。例1類似於C,例2類似於Java(Java'String'存儲長度)。 –
@ElliottFrisch感謝您的評論。糾正我,如果我錯了,但我對x86彙編語言字符串的理解是:字符串可以定義有或沒有null在最後,我們可以確定字符串的長度在最後null,但同樣不能爲沒有null的字符串完成。我的理解是否正確?還有其他的區別嗎? – Thor
考慮還存儲可能包含多個'\ 0'(s)的字符串。我真的不能想到另一個。但也許你可以。祝你好運。 –