memccpy 如何处理大整数值?

How does memccpy handle large integer values?

根据man 3 memccpymemccpy函数定义如下:

SYNOPSIS

#include <string.h>

void *memccpy(void *dest, const void *src, int c, size_t n);

DESCRIPTION

The memccpy() function copies no more than n bytes from memory area src to memory area dest, stopping when the character c is found.

If the memory areas overlap, the results are undefined.

令我困惑的是 memccpy 复制 n 字节并停止 if character c 被发现。但是,该函数将 int c 作为参数。那么如果我用以下值调用 memccpy 会发生什么:

memccpy(&x, &y, 0xffffff76, 100);

这里要检查的值对于 char 来说太大了。这种情况应该有效吗?

how exactly this case is handled in code

只是参数的值被转换为一个字符:

void *memccpy(..., int param_c, ...) {
     unsigned char c = param_c;

现实生活中:https://github.com/lattera/glibc/blob/master/string/memccpy.c#L33 https://github.com/lattera/glibc/blob/master/string/memchr.c#L63 .

(现在的系统)unsigned char有8位,(unsigned char)(int)0xffffff76就变成了0x76。高位被忽略。

这是一个较旧的函数,在接受的参数方面类似于 memset

void *memset(void *s, int c, size_t n);

在C标准中是这样描述的:

The memset function copies the value of c (converted to an unsigned char) into each of the first n characters of the object pointed to by s.

这两个函数至少可以追溯到 4.3 BSD,因此它们以类似的方式处理它们的参数是有道理的。

因此,根据您的示例,值 0xffffff76 将转换为 unsigned char 值 0x76,这将是它检查停止的值。

memccpy() 由 POSIX.1-2001 (IEEE Std 1003.1-2001) 定义,其中规定:

SYNOPSIS

#include <string.h>

void *memccpy(void *restrict s1, const void *restrict s2,
       int c, size_t n);

DESCRIPTION

The memccpy() function shall copy bytes from memory area s2 into s1, stopping after the first occurrence of byte c (converted to an unsigned char) is copied, or after n bytes are copied, whichever comes first. If copying takes place between objects that overlap, the behavior is undefined.

好了,一个简单的 unsigned char 转换发生了:

void *memccpy(void *restrict s1, const void *restrict s2, int c, size_t n) {
    unsigned char actual_c = (unsigned char)c;
    // ...
}

事实上,我所知道的最著名的 C 标准库实现正是这样做的:

  • GNU libc:传递给 memchr,后者执行 unsigned char c = (unsigned int)c_in;
  • BSD libc: unsigned char uc = c;
  • Bionic (Android): 借自 BSD unsigned char uc = c;
  • musl libc: 使用强制转换重新分配 c = (unsigned char)c;
  • uClibc: 在比较中转换:(((unsigned char)(*r1++ = *r2++)) != ((unsigned char) c))