# memccpy

< c‎ | string‎ | byte

定义于头文件 `<string.h>` |  |
void *memccpy(void * restrict dest, const void * restrict src, int c, size_t count); |  | (C23 起)

从 `src` 所指向的对象复制字符到 `dest` 所指向的对象，在满足接下来的任何两个条件之一后停止：

  - 复制了 `count` 个字符
  - 找到（并复制）了字符 (unsigned char)c 。

转译 `src` 与 `dest` 对象为 unsigned char 的数组。

若符合任何以下条件则行为未定义：

  - 出现越过 `dest` 数组结尾的访问
  - 对象重叠（这违反 `restrict` 契约）
  - `dest` 或 `src` 为非法或空指针值

### 参数

dest | - | 指向要复制的对象的指针
src | - | 指向复制来源对象的指针
c | - | 终止字符，首先转换成 unsigned char
count | - | 要复制的字符数

### 返回值

若找到字符 (unsigned char)c 则 `memccpy` 返回 `dest` 中 (unsigned char)c 后一字符的指针，否则返回空指针。

### 注解

函数等同于 POSIX memccpy 。

memccpy(dest, src, 0, count) 表现类似 strncpy(dest, src, count) ，除了前者返回指向被写入缓冲区的末尾的指针，并且不会以零填充目标数组。从而 `memccpy` 对高效连接多个字符串有用。

    char bigString[1000];
    char* end = bigString + sizeof bigString;

    char* p = memccpy(bigString, "John, ", 0, sizeof bigString);
    if (p) p = memccpy(p - 1, "Paul, ", 0, end - p);
    if (p) p = memccpy(p - 1, "George, ", 0, end - p);
    if (p) p = memccpy(p - 1, "Joel ", 0, end - p);

    puts(bigString); // John, Paul, George, Joel

### 示例

    #include <ctype.h>
    #include <stdio.h>
    #include <string.h>

    int main(void)
    {
        const char src[] = "Stars: Altair, Sun, Vega.";
        const char terminal[] = {':', ' ', ',', '.', '!'};
        char dest[sizeof src];
        const char alt = '@';

        for (size_t i = 0; i != sizeof terminal; ++i) {

            void *to = memccpy(dest, src, terminal[i], sizeof dest);

            printf("Terminal '%c' (%s):\t\"", terminal[i], to ? "found" : "absent");

            // 若找不到 `terminal` 字符 - 打印整个 `dest`
            to = to ? to : dest + sizeof dest;

            for (char *from = dest; from != to; ++from)
                putchar(isprint(*from) ? *from : alt);

            puts("\"");
        }

        puts("\n" "Separate star names from distances (ly):");
        const char *star_distance[] = {
            "Arcturus : 37", "Vega : 25", "Capella : 43", "Rigel : 860", "Procyon : 11"
        };
        char names_only[64];
        char *first = names_only;
        char *last = names_only + sizeof names_only;

        for (size_t t = 0; t != (sizeof star_distance)/(sizeof star_distance[0]); ++t) {
            if (first) {
                first = memccpy(first, star_distance[t], ' ', last - first);
            } else break;
        }
        if (first) {
            *first = '\0';
            puts(names_only);
        } else {
            puts("Buffer is too small.");
        }
    }

输出：

    Terminal ':' (found):   "Stars:"
    Terminal ' ' (found):   "Stars: "
    Terminal ',' (found):   "Stars: Altair,"
    Terminal '.' (found):   "Stars: Altair, Sun, Vega."
    Terminal '!' (absent):  "Stars: Altair, Sun, Vega.@"

    Separate star names from distances (ly):
    Arcturus Vega Capella Rigel Procyon

### 参阅

memcpy memcpy_s (C11) | 将一个缓冲区复制到另一个 (函数)
wmemcpy wmemcpy_s (C95)(C11) | 在两个不重叠的数组间复制一定数量的宽字符 (函数)
memmove memmove_s (C11) | 将一个缓冲区移动到另一个 (函数)
strcpy strcpy_s (C11) | 复制一个字符串给另一个 (函数)
strcat strcat_s (C11) | 连接两个字符串 (函数)