命名空间
变体
操作

memcpy, memcpy_s

来自 cppreference.com
< c‎ | string‎ | byte
定义在头文件 <string.h>
(1)
void* memcpy( void *dest, const void *src, size_t count );
(直到 C99)
void* memcpy( void *restrict dest, const void *restrict src, size_t count );
(自 C99 起)
errno_t memcpy_s( void *restrict dest, rsize_t destsz,
                  const void *restrict src, rsize_t count );
(2) (自 C11 起)
1)src 指向的对象复制 count 个字符到 dest 指向的对象。这两个对象都被解释为 unsigned char 数组。
如果访问超出 dest 数组的末尾,行为未定义。如果对象重叠(这违反了 restrict 契约)(自 C99 起),行为未定义。如果 destsrc 是无效的或空指针,则行为未定义。
2)(1) 相同,除了以下错误在运行时被检测到,并导致整个目标范围 [dest, dest+destsz) 被清零(如果 destdestsz 都有效),以及调用当前已安装的 约束处理程序 函数
  • destsrc 是空指针
  • destszcount 大于 RSIZE_MAX
  • count 大于 destsz(将发生缓冲区溢出)
  • 源对象和目标对象重叠
如果 dest 指向的字符数组的大小 < count <= destsz,则行为未定义;换句话说,错误的 destsz 值不会暴露即将发生的缓冲区溢出。
与所有边界检查函数一样,memcpy_s 只有在实现定义了 __STDC_LIB_EXT1__ 并且用户在包含 <string.h> 之前将 __STDC_WANT_LIB_EXT1__ 定义为整数常量 1 时才能保证可用。

内容

[编辑] 参数

dest - 指向要复制到的对象的指针
destsz - 目标中要修改的最大字节数(通常是目标对象的大小)
src - 指向要复制来自的对象的指针
count - 要复制的字节数

[编辑] 返回值

1) 返回 dest 的副本
2) 成功时返回零,错误时返回非零值。同样在错误时,如果 dest 不是空指针并且 destsz 有效,则在目标数组中写入 destsz 个零字节。

[编辑] 备注

memcpy 可用于设置通过分配函数获得的对象的 有效类型

memcpy 是内存到内存复制最快的库例程。它通常比 strcpy 更有效,后者必须扫描它复制的数据,或者比 memmove 更有效,后者必须采取预防措施来处理重叠的输入。

许多 C 编译器将合适的内存复制循环转换为 memcpy 调用。

严格别名 禁止将同一内存检查为两种不同类型的值的情况下,可以使用 memcpy 来转换值。

[编辑] 示例

#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>
#include <stdlib.h>
 
int main(void)
{
    // simple usage
    char source[] = "once upon a midnight dreary...", dest[4];
    memcpy(dest, source, sizeof dest);
    for(size_t n = 0; n < sizeof dest; ++n)
        putchar(dest[n]);
 
    // setting effective type of allocated memory to be int
    int *p = malloc(3*sizeof(int));   // allocated memory has no effective type
    int arr[3] = {1,2,3};
    memcpy(p,arr,3*sizeof(int));      // allocated memory now has an effective type
 
    // reinterpreting data
    double d = 0.1;
//    int64_t n = *(int64_t*)(&d); // strict aliasing violation
    int64_t n;
    memcpy(&n, &d, sizeof d); // OK
    printf("\n%a is %" PRIx64 " as an int64_t\n", d, n);
 
#ifdef __STDC_LIB_EXT1__
    set_constraint_handler_s(ignore_handler_s);
    char src[] = "aaaaaaaaaa";
    char dst[] = "xyxyxyxyxy";
    int r = memcpy_s(dst,sizeof dst,src,5);
    printf("dst = \"%s\", r = %d\n", dst,r);
    r = memcpy_s(dst,5,src,10);            //  count is greater than destsz  
    printf("dst = \"");
    for(size_t ndx=0; ndx<sizeof dst; ++ndx) {
        char c = dst[ndx];
        c ? printf("%c", c) : printf("\\0");
    }
    printf("\", r = %d\n", r);
#endif
}

可能的输出

once
0x1.999999999999ap-4 is 3fb999999999999a as an int64_t
dst = "aaaaayxyxy", r = 0
dst = "\0\0\0\0\0yxyxy", r = 22

[编辑] 参考文献

  • C11 标准 (ISO/IEC 9899:2011)
  • 7.24.2.1 memcpy 函数 (p: 362)
  • K.3.7.1.1 memcpy_s 函数 (p: 614)
  • C99 标准 (ISO/IEC 9899:1999)
  • 7.21.2.1 memcpy 函数 (p: 325)
  • C89/C90 标准 (ISO/IEC 9899:1990)
  • 4.11.2.1 memcpy 函数

[编辑] 另请参见

将一个缓冲区复制到另一个缓冲区,在指定的分隔符后停止
(函数) [编辑]
将一个缓冲区移动到另一个缓冲区
(函数) [编辑]
在两个不重叠的数组之间复制一定数量的宽字符
(函数) [编辑]
C++ 文档 for memcpy