这里没有什么特别的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)的字符串。我真的不能想到另一个。但也许你可以。祝你好运。 –