memmove/memcpy/strcpy 函数的原型中的第二个参数是类似的:
void *memmove(void *dest, const void *src, size_t n); //const void*
char *strcpy(char *dest, const char *src); //const char*
但是显然,如果目标地址和源地址有重叠部分,那么源地址的内容将被更改,这是否违反了const void/char *的限制呢?
const void*
表示通过该指针不会修改引用对象。
如果有其他非常量指针指向同一对象(也称为“别名”),那么当然可以通过它们来修改该对象。在您描述的情况下,另一个指针是dest
。
顺便说一句,在strcpy
的情况下,如果区域重叠,行为是未定义的,并且在C99中签名是char *strcpy(char * restrict s1, const char * restrict s2);
。但是对于memmove,别名是可以的。通过给它重叠的区域,你让它“有权”修改dest
区域,它就会这样做。
参数标记为const void *
,表示memmove
永远不会使用该指针修改指向的内存。如果发生重叠,将使用dest
指针而不是src
指针修改内存,因此保证不会被破坏。
这意味着 memmove
保证不会直接修改由 src
指向的内存。
当然,如果两个块重叠,memmove
将更改所谓的“const”内存。 const
是附加到名称的合同。没有办法使实际内存只读。
dest < src
重叠,则会起作用。如果它们与src < dest
重叠,则在读取之前会覆盖src
结尾处的空字节,然后函数将进入无限循环,破坏内存,直到发生终止事件。但你不能依赖这两种行为。 - Steve Jessop