C语言实现:输入一个字符串,将其循环右移N位。
1.利用strcpy()函数实现:
即将输入pStr的后N位放入temp的前N位,再将pStr所有(到‘\o’结束)放入temp的后面。
假如pStr="12345678",N(nbits)=3,则这时候,temp=“67812345678”,
所以再把temp后面多余部分截掉,最后复制回pStr即完成。
2.利用memcpy()函数实现:
这是在网上看到的另外一种思路。
第一步还是同样将pStr的后N位放入temp的前N位,
但是后面的代码就让人看不懂了。。
第二步它的目的是将pStr的前面部分(length-N)后移N位,就是直接把pStr的前面N个位置“让”出来。但是————
可以这样做?不是有重叠部分吗?拷贝到第N位后会出错吧?还没拷贝出去就被覆盖了呀?
带着这样的疑问,在我的Windows电脑上测试运行:
(方法1和方法2对比结果)
运行结果:
居然是一样的!!!也就是说方法2也是正确的。不敢相信我的眼睛。。。。。。
为什么会这样?
查阅了memcpy()的实现:
不同操作系统下对memcpy()的实现有所差别。
Windows实现:
void * __cdecl memcpy (
void * dst,
const void * src,
size_t count
)
{
void * ret = dst;
#if defined (_M_IA64)//64位
{
extern void RtlMoveMemory( void *, const void *, size_t count );
RtlMoveMemory( dst, src, count );
}
#else
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst 1;
src = (char *)src 1;
}
#endif
return(ret);
}
而Linux实现:
void *memcpy(void *dest, const void *src, size_t count)
{
char *tmp = dest;
const char *s = src;
while (count--)
*tmp = *s ;
return dest;
}
所以在我自己的Windows_64bits系统,是调用RtlMoveMemory( void *, const void *, size_t count )实现。
再查到RtlMoveMemory函数是支持重叠复制的,那么当然memcpy()也支持重叠复制。
这让人想起memcpy()的“兄弟”memmove(),它是支持重叠复制的。
所以得出结论:
在Linux和Win32环境下,用memcpy()实现的方法2是错误的。
而只有, 在Win64环境下正确。
下面是在Linux下的对memcpy()的验证:
方法2的结果错误:
最后:慎用memcpy()!!!注意检查是否有重叠!