能否用memchr实现strnlen?该实现是否存在有效性问题?
关于用memchr实现strnlen的疑问解答
当然可以用memchr来实现strnlen,而且你给出的这段实现是完全有效的!我们来逐个拆解你的疑问:
1. memchr的遍历行为
你之前的假设是错的:memchr并不会无条件遍历全部maxlen字节。它的逻辑是从起始地址开始逐个检查字节,一旦找到目标字符(这里就是'\0')就会立刻停止遍历,返回该字符的指针;只有当遍历完前maxlen个字节都没找到目标字符时,才会走完整个范围并返回NULL。
2. strnlen的行为约定
strnlen的核心规则就是:
- 从
str指向的位置开始,最多检查maxlen个字节; - 如果在这
maxlen字节内找到'\0',返回从str到这个'\0'的偏移量; - 如果全程没找到
'\0',直接返回maxlen。
它的安全前提是:调用者必须保证str指向的内存区域,前maxlen个字节是可访问的(或者在maxlen范围内存在'\0',此时访问会在终止符处停止)。这和memchr的要求完全匹配,所以用memchr实现是完全符合约定的。
3. 关于无效内存访问的判断
你的这个判断是正确的,但这并不是这个实现的问题——而是strnlen本身的调用前提问题。
不管你是用memchr实现,还是手动写循环遍历,只要调用strnlen时:
str指向的内存实际有效大小小于maxlen,且- 这段内存里没有
'\0'终止符
那么程序都会访问到无效内存区域。这是调用者需要承担的责任:调用strnlen时必须确保maxlen不超过str所在内存的有效长度,或者str在maxlen范围内存在终止符。
再看你的实现代码
这段代码完全符合strnlen的语义:
size_t strnlen(const char *str, size_t maxlen) { char *nul = memchr(str, '\0', maxlen); return nul ? (size_t)(nul - str) : maxlen; }
而且还有额外的优势:memchr通常是标准库中经过高度优化的函数(比如用硬件指令批量检查字节),性能往往比手动写的循环更好。
内容的提问来源于stack exchange,提问作者JudeMH
相关产品推荐
相关产品推荐

