在memmove函数中,"const void*"是什么意思?

10

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 *的限制呢?

4个回答

20

const void* 表示通过该指针不会修改引用对象。

如果有其他非常量指针指向同一对象(也称为“别名”),那么当然可以通过它们来修改该对象。在您描述的情况下,另一个指针是dest

顺便说一句,在strcpy的情况下,如果区域重叠,行为是未定义的,并且在C99中签名是char *strcpy(char * restrict s1, const char * restrict s2);。但是对于memmove,别名是可以的。通过给它重叠的区域,你让它“有权”修改dest区域,它就会这样做。


你的意思是,如果我不能确定dest和src是否重叠,那么最好不要使用strcpy,对吗? - Alcott
1
@Alcott:没错。在实践中,你最可能看到的是,如果你的区域与 dest < src 重叠,则会起作用。如果它们与 src < dest 重叠,则在读取之前会覆盖 src 结尾处的空字节,然后函数将进入无限循环,破坏内存,直到发生终止事件。但你不能依赖这两种行为。 - Steve Jessop

7

参数标记为const void *,表示memmove永远不会使用该指针修改指向的内存。如果发生重叠,将使用dest指针而不是src指针修改内存,因此保证不会被破坏。


4

这意味着 memmove 保证不会直接修改由 src 指向的内存。

当然,如果两个块重叠,memmove 将更改所谓的“const”内存。 const 是附加到名称的合同。没有办法使实际内存只读。


@Praetorian 我经常不知道我在说什么,但我喜欢评论,这样我就可以学习 :-) - cnicutar

4
如上所述,memove函数不会通过“src”指针修改内存内容,但会通过“dest”指针进行修改。
“const”是指针的使用方式,它不会添加任何内存保护。
如果两个指针都指向重叠的内存区域,则任何事情都可能发生,因为未定义复制将从“src”和递增开始,还是从“src + n”和递减开始。

抱歉看起来像是重复的答案,但我是在上面被编辑的同时发布的。 - John Beckett
那种事情经常发生,不是问题。即使答案基本相同,通常也会有微妙的差异,而且经常拥有几个相同事物的解释非常有用——一个读者可能最好理解其中之一,而另一个人则可能理解另一个解释。 - Steve Jessop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接