memmove, memmove_s
来自 cppreference.cn
定义于头文件 <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 <inttypes.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.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
[编辑] 参考文献
- C23 标准 (ISO/IEC 9899:2024)
- 7.24.2.2 memmove 函数 (p: TBD)
- K.3.7.1.2 memmove_s 函数 (p: TBD)
- 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++ 文档 关于 memmove
|