memcpy, memcpy_s
来自cppreference.com
                    
                                        
                    
                    
                                                            
                    |   定义于头文件  <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 的数组。2) 同 (1) ,除了错误时导致清零整个目标范围 [dest, dest+destsz) (若 
dest 与 destsz 均合法),它在运行时检测下列错误,并调用当前安装的制约处理函数:
-  
dest或src为空指针 -  
destsz或count大于 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]); // 设置分配的内存的有效类型为 int int *p = malloc(3*sizeof(int)); // 分配的内存无有效类型 int arr[3] = {1,2,3}; memcpy(p,arr,3*sizeof(int)); // 分配的内存现在拥有有效类型 // reinterpreting data double d = 0.1; // int64_t n = *(int64_t*)(&d); // 严格别名使用违规 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 大于 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 standard (ISO/IEC 9899:2011):
 
- 7.24.2.1 The memcpy function (p: 362)
 
- K.3.7.1.1 The memcpy_s function (p: 614)
 
- C99 standard (ISO/IEC 9899:1999):
 
- 7.21.2.1 The memcpy function (p: 325)
 
- C89/C90 standard (ISO/IEC 9899:1990):
 
- 4.11.2.1 The memcpy function
 
参阅
|    (C23)  | 
   复制一个缓冲区到另一个,在指定的分隔符后停止   (函数)  | 
|    (C11)  | 
   将一个缓冲区移动到另一个  (函数)  | 
|    (C95)(C11)  | 
   在两个不重叠的数组间复制一定数量的宽字符  (函数)  |