返回信息流void MemCopy(int *from,int*to,int n)
{
if(from==NULL||to==NULL||n<0)
return;
int i;
if(from<=to)
{
for (i=0;i<n;i++)
{
*((char *)(to+i))=*((char *)(from+i));
}
}
else
{
for (i=n-1;i>=0;i--)
{
*((char *)(to+i))=*((char *)(from+i));
}
}
}
这是在某处看到的实现mencpy()的代码,但不明白为什么要用*((char *)(to+i))=*((char *)(from+i));
*(to+i)=*(from+i)运行时一样正确啊?
这是一条镜像帖。来源:北邮人论坛 / cpp / #74726同步于 2013/10/23
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖
看到的一个程序,不大明白!
HFlyaway
2013/10/23镜像同步11 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
这是函数模拟库函数void * memcpy ( void * destination, const void * source, size_t num );
其中num参数表示需要拷贝的字节数。请参考:
http://www.cplusplus.com/reference/cstring/memcpy/
你给的程序中,之所以要使用*((char *)(to+i))=*((char *)(from+i));是因为char类型在内存中就占用一个字节,而*(to+i)每次得到的是int类型,32位系统中占4个字节,和库函数memcpy的目的不符了。
这个实现有误导,多找几个对比下,然后自己再完整的写下来
【 在 HFlyaway 的大作中提到: 】
: void MemCopy(int *from,int*to,int n)
: {
: if(from==NULL||to==NULL||n<0)
: ...................
【 在 rollse 的大作中提到: 】
: 这是函数模拟库函数void * memcpy ( void * destination, const void * source, size_t num );
: 其中num参数表示需要拷贝的字节数。请参考:
: http://www.cplusplus.com/reference/cstring/memcpy/
: ...................
为什么在具体调试的时候如果函数memcpy ( void * destination, const void * source, size_t num )会提示error C2036: “void *”: 未知的大小,必须改成memcpy ( int* destination, const int * source, size_t num )才行,也就是“不允许对一个指向未知尺寸类型(unknown size)的指针进行直接运算”,但是这里并不确定要copy的是什么类型的数据,要怎么解决呢?
【 在 rollse 的大作中提到: 】
: 这是函数模拟库函数void * memcpy ( void * destination, const void * source, size_t num );
: 其中num参数表示需要拷贝的字节数。请参考:
: http://www.cplusplus.com/reference/cstring/memcpy/
: ...................
看了之后感觉我上面的那种实现方法就不对,他不是copy的连续的四个字节,
#include<iostream>
using namespace std;
void * MemCopy(void *dest, const void * source,int count)
{
//用于最后返回
char *ret = (char *)dest;
//用来逐字节拷贝
char *dest_t = ret;
char *source_t = (char *)source;
while (count--){
*dest_t++ = *source_t++;
}
return ret;
}
int main(void)
{
int x = 4,y = 8;
cout<<"x = "<<x<<" y = "<<y<<endl;
//拷贝y的前4个字节到x
MemCopy(&y,&x,4);
cout<<"x = "<<x<<" y = "<<y<<endl;
}
注意返回值和库函数原型保持一致,你之前的实现是错误的,因为 *((char *)(to+i))=*((char *)(from+i));这句里面每次加的时候步长是4,int的sizeof,不是按字节拷贝了,而是每个int对象4个字节中的前一个字节被拷贝了。
上面的代码编译通过,运行正常,你试试
【 在 HFlyaway 的大作中提到: 】
: 为什么在具体调试的时候如果函数memcpy ( void * destination, const void * source, size_t num )会提示error C2036: “void *”: 未知的大小,必须改成memcpy ( int* destination, const int * source, size_t num )才行,也就是“不允许对一个指向未知尺寸类型(unknown size)的指针进行直接运算”,但是这里并不确定要copy的是什么类型的数据,要怎么解决呢?
这个实现没问题,但其实没必要再声明变量dest_t和source_t,因为dest和source本身是形参。
【 在 rollse 的大作中提到: 】
: #include<iostream>
: using namespace std;
: void * MemCopy(void *dest,void * source,int count)
: ...................
我修改了函数原型和库函数memcpy保持一直,也就是source用const void * source方式传入。由于传入的指针指向的数据类型不定,自增每次增加的字节长度也就不定,比如如果是double类型的话,那就是8字节了。所以定义局部变量source_t就是必要的,让source_t指向source所指内存的开始,而且是source_t是指向char的指针,就是1个字节。以后自增每次加1就是移动一个字节,符合memcpy的定义。
如果非要改进的话,可以这样:
#include<iostream>
#include "assert.h"
using namespace std;
void * MemCopy(void *dest, const void * source,size_t count)
{
assert(dest != NULL && source != NULL && count >=0);
char *dest_t = (char *)dest;
char *source_t = (char *)source;
for(size_t copiedBytes = 1; copiedBytes <= count; ++copiedBytes)
{
*dest_t++ = *source_t++;
}
return dest_t - count;
}
int main(void)
{
int x = 4,y = 8;
cout<<"x = "<<x<<" y = "<<y<<endl;
//拷贝y的前4个字节到x
int * returnValue = (int *)MemCopy(&y,&x,4);
cout<<"using MemCopy, x = "<<x<<" y = "<<y<<endl;
//检查返回的地址,应该和dest相同
assert(returnValue == &y);
cout<<"using MemCopy, returnValue = "<<*returnValue<<endl;
y = 8;
returnValue = (int *)memcpy(&y,&x,4);
cout<<"using memcpy, x = "<<x<<" y = "<<y<<endl;
//检查返回的地址,应该和dest相同
assert(returnValue == &y);
cout<<"using memcpy, returnValue = "<<*returnValue<<endl;
}
可以看到现在我们的函数和库函数的原型和行为都是一致的了。
【 在 li375268037 的大作中提到: 】
: 这个实现没问题,但其实没必要再声明变量dest_t和source_t,因为dest和source本身是形参。
我翻出来以前写的一个memmove
void *my_memmove(void *dst, const void *src, int count){
void *start = dst;
if(dst < src || src + count <= dst){
while(count--) *(char *)dst++ = *(char *)(src++);
}
else{
dst += count - 1;
src += count - 1;
while(count--) *(char *)dst-- = *(char *)src--;
}
return start;
}
还有一个概念,const void * 修饰的是指向的内容是常量,而void * const 修饰的指针是常量。前者指针可以自增,后者指针不可以。
【 在 rollse 的大作中提到: 】
: 我修改了函数原型和库函数memcpy保持一直,也就是source用const void * source方式传入,无法修改,不能执行自增,而且传入的指针指向的数据类型不定,自增每次增加的字节长度也就不定,比如如果是double类型的话,那就是8字节了。所以定义局部变量source_t就是必要的,让source_t指向source所指内存的开始,而且是source_t是指向char的指针,就是1个字节。以后自增每次加1就是移动一个字节,符合memcpy的定义。
: 如果非要改进的话,可以这样:
: #include<iostream>
: ...................