memmove
memmove, memmove_s
在头文件 | | |
---|---|---|
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指向的对象中的字符到dest指向的对象。 两个对象都被解释为无符号字符数组。 这些对象可能会重叠:复制发生就像将这些字符复制到一个临时字符数组,然后将这些字符从该数组复制到dest一样。
如果访问超出dest
数组的末尾,则行为未定义。如果dest
或者src
其中之一是空指针,行为是未定义的。
2)与(1)相同,除了在运行时检测到以下错误,它会将整个目标范围[dest,dest + destsz)清零(如果dest和destsz都有效)并调用当前安装的约束处理函数:
dest
或者src
是空指针
如果由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
可用于设置由分配函数获得的对象的有效类型。
尽管被指定为“as if”使用了临时缓冲区,但该函数的实际实现不会产生开销或双重复制或额外的内存。 一种常用的方法(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
参考
- C11标准(ISO / IEC 9899:2011):
扩展内容
memcpymemcpy_s(C11) | 将一个缓冲区复制到另一个(功能) |
---|---|
wmemmovewmemmove_s(C95)(C11) | 在两个可能重叠的数组之间复制一定数量的宽字符(函数) |
| memmove的C ++文档 |