memcpy, memcpy_s

来自cppreference.com
< c‎ | string‎ | byte
在标头 <string.h> 定义
(1)
void* memcpy(void*dest, constvoid*src, size_t count );
(C99 前)
void* memcpy(void*restrict dest, constvoid*restrict src, size_t count );
(C99 起)
errno_t memcpy_s(void*restrict dest, rsize_t destsz,
                  constvoid*restrict src, rsize_t count );
(2) (C11 起)
1)src 所指向的对象复制 count 个字符到 dest 所指向的对象。两个对象都被转译成 unsignedchar 的数组。
若在 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 的副本,本质为更底层操作的临时内存地址,在实际操作中不建议直接使用此地址,操作完成以后,真正有意义的地址是 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){// 简单用法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]);   // 设置分配的内存的有效类型为 intint*p =malloc(3*sizeof(int));// 分配的内存无有效类型int arr[3]={1,2,3}; memcpy(p,arr,3*sizeof(int));// 分配的内存现在拥有有效类型   // reinterpreting datadouble d =0.1;// int64_t n = *(int64_t*)(&d); // 严格别名使用违规int64_t n; memcpy(&n, &d, sizeof d);// OKprintf("\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 大于 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 The memcpy function (第 362 页)
  • K.3.7.1.1 The memcpy_s function (第 614 页)
  • C99 标准(ISO/IEC 9899:1999):
  • 7.21.2.1 The memcpy function (第 325 页)
  • C89/C90 标准(ISO/IEC 9899:1990):
  • 4.11.2.1 The memcpy function

[编辑]参阅

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