strnlen可以用memchr实现吗?

Can strnlen be implemented with memchr?

下面的strnlen执行是否无效?

size_t strnlen(const char *str, size_t maxlen)
{
    char *nul = memchr(str, '[=10=]', maxlen);
    return nul ? (size_t)(nul - str) : maxlen;
}

我假设 memchr 可能总是查看 maxlen 个字节,无论这些字节的内容如何。如果没有 NUL 终止符,strnlen 的合同是否只允许它查看所有 maxlen 字节?如果是这样,str 的内存大小可能小于 maxlen 字节,在这种情况下 memchr 可能会尝试读取无效的内存位置。这是正确的吗?

I assume that memchr may always look at maxlen bytes no matter the contents of those bytes.

这个假设是错误的。 From POSIX:

Implementations shall behave as if they read the memory byte by byte from the beginning of the bytes pointed to by s and stop at the first occurrence of c (if it is found in the initial n bytes).

是的,发布的实现是符合的:memchr() 不应该从 str 中读取超过第一次出现的 '[=13=]' 的字节。

C17 7.24.5.1 The memchr function

Synopsis

#include <string.h>
void *memchr(const void *s, int c, size_t n);

Description

The memchr function locates the first occurrence of c (converted to an unsigned char) in the initial n characters (each interpreted as unsigned char) of the object pointed to by s. The implementation shall behave as if it reads the characters sequentially and stops as soon as a matching character is found.

Returns

The memchr function returns a pointer to the located character, or a null pointer if the character does not occur in the object.

memchr 可以使用一次测试多个字节的高效技术来实现,可能会读取第一个匹配字节之外的内容,但前提是这不会导致任何可见的副作用。