memcpy函数的实现代码

Dejia 2003-01-24 09:59:22
请大虾给出memcpy函数的实现代码(面试急用)
thanks!
...全文
947 17 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
loxihu 2003-08-22
  • 打赏
  • 举报
回复
VC:

void* Dest=(void*)pSurf;
void* Src = (void*)pBuffer;
size_t nBytes = (size_t)buffLen;
_asm
{
push edi
push esi

mov esi, dword ptr[Src]
mov edi, dword ptr[Dest]
mov ecx, nBytes
shr ecx, 6 ; nBytes / 64
align 4
Memcpy_Loop:
movq mm0, qword ptr[esi]
movq mm1, qword ptr[esi+8*1]
movq mm2, qword ptr[esi+8*2]
movq mm3, qword ptr[esi+8*3]
movq mm4, qword ptr[esi+8*4]
movq mm5, qword ptr[esi+8*5]
movq mm6, qword ptr[esi+8*6]
movq mm7, qword ptr[esi+8*7]
movq qword ptr[edi], mm0
movq qword ptr[edi+8*1], mm1
movq qword ptr[edi+8*2], mm2
movq qword ptr[edi+8*3], mm3
movq qword ptr[edi+8*4], mm4
movq qword ptr[edi+8*5], mm5
movq qword ptr[edi+8*6], mm6
movq qword ptr[edi+8*7], mm7
add esi, 64
add edi, 64
loop Memcpy_Loop

mov ecx, nBytes
and ecx, 63
cmp ecx, 0
je Memcpy_End
rep movsb
Memcpy_End:
emms
pop esi
pop edi
}
asvaboy1980 2003-01-28
  • 打赏
  • 举报
回复
gz
dximg 2003-01-28
  • 打赏
  • 举报
回复
的确memcpy讲求的是效率,下面的代码是c库的实现代码
看一看大师是怎样考虑的。

typedef int word; /* "word" used for optimal copy speed */

#define wsize sizeof(word)
#define wmask (wsize - 1)

void *
memcpy(void *dst0, const void *src0, size_t length)
{
char *dst = dst0;
const char *src = src0;
size_t t;

if (length == 0 || dst == src) /* nothing to do */
goto done;

/*
* Macros: loop-t-times; and loop-t-times, t>0
*/
#define TLOOP(s) if (t) TLOOP1(s)
#define TLOOP1(s) do { s; } while (--t)

if ((unsigned long)dst < (unsigned long)src) {
/*
* Copy forward.
*/
t = (int)src; /* only need low bits */
if ((t | (int)dst) & wmask) {
/*
* Try to align operands. This cannot be done
* unless the low bits match.
*/
if ((t ^ (int)dst) & wmask || length < wsize)
t = length;
else
t = wsize - (t & wmask);
length -= t;
TLOOP1(*dst++ = *src++);
}
/*
* Copy whole words, then mop up any trailing bytes.
*/
t = length / wsize;
TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
t = length & wmask;
TLOOP(*dst++ = *src++);
} else {
/*
* Copy backwards. Otherwise essentially the same.
* Alignment works as before, except that it takes
* (t&wmask) bytes to align, not wsize-(t&wmask).
*/
src += length;
dst += length;
t = (int)src;
if ((t | (int)dst) & wmask) {
if ((t ^ (int)dst) & wmask || length <= wsize)
t = length;
else
t &= wmask;
length -= t;
TLOOP1(*--dst = *--src);
}
t = length / wsize;
TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
t = length & wmask;
TLOOP(*--dst = *--src);
}
done:
return (dst0);
}

BigTall 2003-01-27
  • 打赏
  • 举报
回复
都说些什么啊?!看看真正的C/C++库的是现代码吧

Func@ memmove, _EXPFUNC, _RTLENTRYF, <pointer dest>,<pointer src>,<int n>

Link@ esi,edi
mov edi,dest
mov esi,src
mov ecx,n
mov edx,ecx
cmp edi,esi ; dest < source ?
jb mov_fwd ; yes, do a simple forward move
je mov_end ; dest == source ? do nothing
std ; force esi and edi to decrement
lea esi,[esi+ecx-1] ; point to last byte of source buffer
lea edi,[edi+ecx-1] ; point to last byte of dest buffer
and ecx,3 ; copy trailing bytes
rep movsb
mov ecx,edx ; get original count back
shr ecx,1 ; calculate no. of longwords
shr ecx,1
sub esi,3 ; point to previous longword in source
sub edi,3 ; point to previous longword in dest
rep movsd ; copy longwords
cld ; clear direction flag
jmp short mov_end
mov_fwd:
cld
shr ecx,1
shr ecx,1
rep movsd ; copy longwords
mov ecx,edx ; get original count back
and ecx,3 ; calculate remainder byte count (0-3)
rep movsb ; copy remaining bytes
mov_end:
mov eax,dest
Unlink@ esi,edi
Return@

EndFunc@ memmove

做几件事情:
1。内存自身拷贝问题
2。有相交重叠的两块内存的拷贝问题
3。拷贝速度的问题

对于拷贝速度问题,方法是32位机器上双字对齐边界开始拷贝,16位机器上字边界开始拷贝,把内存分为3段:

对齐边界之前的字节,对齐拷贝的字节,最后对齐边界之后的字节

第一段使用一个movsb和movsw完成任务,第二段采用movsd完成,第三段也采用一个movsw和movsb完成。

面试过程只要说出这三个要点就可以了,程序其实你可以不用编写了

刚才拷贝部分的等价操作如下
memmove(char * src,char *dest, int n) // <-- 实际定义是void *

if( 0 != (long(dest) & 0x1)) O
n--, (*dest++ = *src++);

if( 0 != (long(dest) & 0x2)) {
*(short*)dest++ = *(short*)src++;
n--; n--;
}

int c = n / 4;
while( c -- )
*(long*)dest++ = *(long*)src++;

int k = n %4;
if( k >= 2 ) *(short*)dest++ = *(short*)src++;
if( k == 1 ) *dest++ = src++;



其他再加上一些if判断就可以了


Davidzhuhua 2003-01-27
  • 打赏
  • 举报
回复
#include <string.h>

void *
memcpy(void *s1, const void *s2, register size_t n)
{
register char *p1 = s1;
register const char *p2 = s2;


if (n) {
n++;
while (--n > 0) {
*p1++ = *p2++;
}
}
return s1;
}
operaphantom 2003-01-26
  • 打赏
  • 举报
回复
extern void *
MEMCPY ( void *pDest, const void *pSrc, Length size )
{
Counter cNumBytes;
char *pD, *pS;

if ((NULL == pSrc) || (NULL == pDest))
return NULL;

pD = ( char * ) pDest;
pS = ( char * ) pSrc;
cNumBytes = 0;

while ( cNumBytes < size )
{
*pD++ = *pS++;
cNumBytes++;
}

return pDest;

}
brucegong 2003-01-26
  • 打赏
  • 举报
回复




C里面定义的memcpy讲求的是快,没有保证任何的安全性。某君画蛇添足了





robin97 2003-01-26
  • 打赏
  • 举报
回复
void * memmove(void * dst, void * src, size_t count)
; {
; void * ret = dst;
;
; if (dst <= src || dst >= (src + count)) {
; /*
; * Non-Overlapping Buffers
; * copy from lower addresses to higher addresses
; */
; while (count--)
; *dst++ = *src++;
; }
; else {
; /*
; * Overlapping Buffers
; * copy from higher addresses to lower addresses
; */
; dst += count - 1;
; src += count - 1;
;
; while (count--)
; *dst-- = *src--;
; }
;
; return(ret);
; }
Cybergate 2003-01-26
  • 打赏
  • 举报
回复
抱歉,有个bug,改之
void _fmemcpy(void far *dest, void far* src, long n)
{
 do
*((char far*)dest)=*((char far*)src);
while (n-=sizeof(char));
}
dtc030 2003-01-26
  • 打赏
  • 举报
回复
哇!!!!!!!!
一个这么简单的问题提出来都已经觉得好笑,还要改来改去,
我真的不知道怎么说好了。
Cybergate 2003-01-25
  • 打赏
  • 举报
回复
请问qhgary(Shining): 你的方法我好像更不能理解, 为什么要判断'\0'呢? 这又不是拷贝字符串.

楼主: 我的程序是这样的:

void _fmemcpy(void far *dest, void far* src, long n)
{
while (n-=sizeof(char)) *((char far*)dest)=*((char far*)src);
}

不过,在32位语言中,far是不必要的
Cybergate 2003-01-25
  • 打赏
  • 举报
回复
有2个问题:

1. n不就是要拷贝的字节数?为什么还要乘以sizeof(size_t)? 是sizeof(char)吧?

2. 为什么要far指针呢?是不是要考虑跨段拷贝的情形?
robin97 2003-01-25
  • 打赏
  • 举报
回复
看看vc里的程序,c的有,汇编得也有,保证经典
qhgary 2003-01-25
  • 打赏
  • 举报
回复
不小心打掉了个括号 最后一个while后面用括号括上
qhgary 2003-01-25
  • 打赏
  • 举报
回复
改进一下,这样我觉得更安全一点

void memcpy( void * dest, void * src , size_t n)
{
char far * pd = (char far * )dest;
char far * ps = (char far * )src;
long len = (long)sizeof(size_t) * n;
while(len)
{
while(*pd++ = *ps++)!='\0'
len--;
}
}
tuxw 2003-01-24
  • 打赏
  • 举报
回复
可以适应多种数据类型

void memcpy( void * dest, void * src , size_t n)
{
char far * pd = (char far * )dest;
char far * ps = (char far * )src;
long len = (long)sizeof(size_t) * n;

for( long i=0; i<n; ++i )
*pd++ = *ps++;
}
qhgary 2003-01-24
  • 打赏
  • 举报
回复
gz

70,029

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧