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
的副本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)