如果您知道在到达有效区域的末尾之前找到该字符,那么调用长度过长的memchr是否合法?

在C11和C ++ 11 1中是否有以下定义的行为?

bool has4() { char buf[10] = {0, 1, 2, 4}; return memchr(buf, 4, 20); } 

在这里,我们通过一个太长的长度memchr 。 数组有10个元素,但是我们传递了20.但是,我们搜索的元素总是在结束之前找到。 我很清楚这是否合法。

如果允许这样做,则会限制实现的灵活性,因为实现不能依赖于大小是可访问存储器区域大小的有效指示,因此必须小心读取超出找到的元素。 一个例子是希望从传入指针开始执行16字节SIMD加载然后并行检查所有16个字节的实现。 如果用户传递的长度为16,则只有在需要访问整个长度时才会安全。

否则(如果上面的代码是合法的),实现必须避免对目标元素之外的元素进行潜在的error handling,例如通过对齐加载(可能很昂贵)或检查指针是否接近保护边界的末尾 。


1这是一个罕见的问题,我猜C和C ++的标记是有效的:据我所知,C ++标准只是在行为方面直接推迟到C标准,但是如果不是这样的话我想知道。

在C11和C ++ 17( 强调我的

void *memchr(const void *s, int c, size_t n);

memchr函数在s指向的对象的初始n字符(每个解释为unsigned char )中定位第一次出现的c (转换为unsigned char )。 实现的行为就像它按顺序读取字符一样,并在找到匹配的字符后立即停止。

只要memchr在您走出界限之前找到了它正在寻找的东西,你就可以了。


C ++ 11和C ++ 14都使用C99,它没有这样的措辞。 (他们参考ISO / IEC 9899:1999)

C99措辞:

void *memchr(const void *s, int c, size_t n);

memchr函数在s指向的对象的初始n字符(每个解释为unsigned char )中定位第一次出现的c (转换为unsigned char )。

通过不定义如果传递太大的大小会发生什么,行为在C99中是未定义