memcpy, memcpy_s
From cppreference.net
|
定义于头文件
<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
的错误值不会暴露即将发生的缓冲区溢出。
-
与所有边界检查函数一样,仅当实现定义了
__STDC_LIB_EXT1__
且用户在包含
<string.h>
前将
__STDC_WANT_LIB_EXT1__
定义为整型常量
1
时,才保证
memcpy_s可用。
目录 |
参数
| 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) { // 简单用法 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)); // 分配的内存现在具有有效类型 // 重新解释数据 double d = 0.1; // int64_t n = *(int64_t*)(&d); // 严格别名违规 int64_t n; memcpy(&n, &d, sizeof d); // 正确 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 标准 (ISO/IEC 9899:2011):
-
- 7.24.2.1 memcpy 函数 (第 362 页)
-
- K.3.7.1.1 memcpy_s 函数 (第 614 页)
- C99 标准 (ISO/IEC 9899:1999):
-
- 7.21.2.1 memcpy 函数 (第 325 页)
- C89/C90 标准 (ISO/IEC 9899:1990):
-
- 4.11.2.1 memcpy 函数
另请参阅
|
(C23)
|
复制一个缓冲区到另一个缓冲区,遇到指定分隔符后停止
(函数) |
|
(C11)
|
移动一个缓冲区到另一个缓冲区
(函数) |
|
(C95)
(C11)
|
在两个非重叠数组间复制指定数量的宽字符
(函数) |
|
C++ 文档
for
memcpy
|
|