memmove, memmove_s
来自 cppreference.com
定义在头文件 <string.h> 中 |
||
void* memmove( void* dest, const void* src, size_t count ); |
(1) | |
errno_t memmove_s(void *dest, rsize_t destsz, const void *src, rsize_t count); |
(2) | (自 C11) |
1) 将由
src
指向的对象中的 count
个字符复制到由 dest
指向的对象中。这两个对象都被解释为 unsigned char 数组。这些对象可能重叠:复制发生在将字符复制到一个临时字符数组中,然后将字符从该数组复制到 dest
中。 如果访问发生在 dest 数组的末尾之外,则行为未定义。如果
dest
或 src
是无效的或空指针,则行为未定义。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 时,才保证
memmove_s
可用。
内容 |
[编辑] 参数
dest | - | 指向要复制到的对象的指针 |
destsz | - | 要修改的目标中的最大字节数(通常是目标对象的大小) |
src | - | 指向要复制的源对象的指针 |
count | - | 要复制的字节数 |
[编辑] 返回值
1) 返回
dest
的副本2) 成功时返回零,错误时返回非零值。此外,如果
dest
不是空指针并且 destsz
有效,则错误时会在目标数组中写入 destsz
个零字节。[编辑] 说明
memmove
可用于设置由分配函数获取的对象的 有效类型。
尽管指定为“好像”使用了一个临时缓冲区,但此函数的实际实现不会产生开销或双重复制或额外内存。一种常见的方法(glibc 和 bsd libc)是,如果目标在源之前开始,则从缓冲区的开头向前复制字节,否则从末尾向后复制字节,当完全没有重叠时,则回退到更有效的 memcpy。
在 严格别名 禁止将同一内存视为两种不同类型的值的场合,memmove
可用于转换这些值。
[编辑] 示例
运行此代码
#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 str[] = "1234567890"; puts(str); memmove(str+4, str+3, 3); // copy from [4,5,6] to [5,6,7] puts(str); // 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}; memmove(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; memmove(&n, &d, sizeof d); // OK printf("%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 = memmove_s(dst,sizeof dst,src,5); printf("dst = \"%s\", r = %d\n", dst,r); r = memmove_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 }
可能的输出
1234567890 1234456890 0x1.999999999999ap-4 is 3fb999999999999a as an int64_t dst = "aaaaayxyxy", r = 0 dst = "\0\0\0\0\0yxyxy", r = 22
[编辑] 参考
- C17 标准 (ISO/IEC 9899:2018)
- 7.24.2.2 memmove 函数 (p: 264)
- K.3.7.1.2 memmove_s 函数 (p: 446)
- C11 标准 (ISO/IEC 9899:2011)
- 7.24.2.2 memmove 函数 (p: 363)
- K.3.7.1.2 memmove_s 函数 (p: 615)
- C99 标准 (ISO/IEC 9899:1999)
- 7.21.2.2 memmove 函数 (p: 326)
- C89/C90 标准 (ISO/IEC 9899:1990)
- 4.11.2.2 memmove 函数
[编辑] 另请参阅
(C11) |
将一个缓冲区复制到另一个缓冲区 (函数) |
(C95)(C11) |
在两个可能重叠的数组之间复制一定数量的宽字符 (函数) |
C++ 文档 for memmove
|