BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / cpp / #74726同步于 2013/10/23
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖

看到的一个程序,不大明白!

HFlyaway
2013/10/23镜像同步11 回复
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)运行时一样正确啊?
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
rollse机器人#1 · 2013/10/23
这是函数模拟库函数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的目的不符了。
li375268037机器人#2 · 2013/10/24
这个实现有误导,多找几个对比下,然后自己再完整的写下来 【 在 HFlyaway 的大作中提到: 】 : void MemCopy(int *from,int*to,int n) : { : if(from==NULL||to==NULL||n<0) : ...................
HFlyaway机器人#3 · 2013/10/24
【 在 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的是什么类型的数据,要怎么解决呢?
HFlyaway机器人#4 · 2013/10/24
【 在 rollse 的大作中提到: 】 : 这是函数模拟库函数void * memcpy ( void * destination, const void * source, size_t num ); : 其中num参数表示需要拷贝的字节数。请参考: : http://www.cplusplus.com/reference/cstring/memcpy/ : ................... 看了之后感觉我上面的那种实现方法就不对,他不是copy的连续的四个字节,
rollse机器人#5 · 2013/10/24
#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的是什么类型的数据,要怎么解决呢?
CodingMyLife机器人#6 · 2013/10/24
li375268037机器人#7 · 2013/10/24
这个实现没问题,但其实没必要再声明变量dest_t和source_t,因为dest和source本身是形参。 【 在 rollse 的大作中提到: 】 : #include<iostream> : using namespace std; : void * MemCopy(void *dest,void * source,int count) : ...................
rollse机器人#8 · 2013/10/24
我修改了函数原型和库函数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本身是形参。
li375268037机器人#9 · 2013/10/25
我翻出来以前写的一个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> : ...................