c - memccpy 如何处理大整数values?

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

SYNOPSIS

#include <string.h>

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

DESCRIPTION

memccpy() 函数将不超过 n 个字节从内存区域 src 复制到内存区域 dest,当找到字符 c

如果内存区域重叠,则结果未定义。

令我困惑的是 memccpy 复制 n 字节并在找到字符 c 时停止。但是,该函数将 int c 作为参数。那么如果我用下面的 value 调用 memccpy 会发生什么:

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

这里要检查的 value 对于 char 来说太大了。这个案子应该管用吗?

回答1

memccpy() 由 POSIX.1-2001 (https://pubs.opengroup.org/onlinepubs/009695399/) 定义,其中规定:

SYNOPSIS

#include <string.h>

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

DESCRIPTION

memccpy() 函数应将字节从内存区域 s2 复制到 s1,在第一次出现字节 (转换为无符号字符)被复制,或在复制 n 个字节后,以先到者为准。如果复制发生在重叠的对象之间,则行为未定义。

所以你去,一个简单的 unsigned char 转换发生:

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

事实上,我所知道的最突出的 C standard library 实现正是这样做的:

回答2

这种情况在代码中究竟是如何处理的

只是将参数的 value 转换为字符:

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。高位被忽略。

回答3

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

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

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

memset 函数将 c 的 value(转换为 unsigned char)复制到 s 指向的对象的前 n 字符中。

两个函数 date 至少回到 4.3 BSD,因此它们以类似的方式处理它们的参数是有意义的。

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