c语言实现memcpy
今天到I 公司去面試,面試方式比較特殊,沒有筆試,就是2 個面試官,一人一句輪番發問,涉及面很廣,涉及到操作系統(MMU 、page out 、process/thread 、semaphore 、interrupt), OOP( 多態、design pattern) 、數據結構( 排序、二叉查找樹) 、計算機網絡(OSI 5 層) 、C 語言(big/small endian) 、英語口語等等,問了大約一個小時左右。
所有問題都是口頭表述,只在紙上寫了一個memcpy 程序,用C 語言實現,腦子一發蒙,既然寫成了strcpy ,真該死。
回家了查詢了一下memcpy 定義,如下:
Void *memcpy(void *dest, const void *src, unsigned int count);
查詢msdn, 發現Remark 如下:
memcpy copies count bytes from src to dest ; If the source and destination overlap, the behavior of memcpy is undefined. Use memmove to handle overlapping regions.
以上描述針對dest 和 src 所指的內存地址有重疊的情況,內存地址重疊情況,memcpy 函數處理步驟未定,而memmove 對重疊情況給予處理;
在winXP+visual c++2005 測試 memcpy 函數,程序如下:
?
#include "stdafx.h"
#include <string.h>
int _tmain (int argc , _TCHAR * argv [])
{
?????? char s [16] = "aabbcc" ;
?????? char d [16] = {0};
??????
?????? memcpy (s +2, s , 4);
?????? printf ("%s" , s );
?????? return 0;
}
結果輸出 “aaaabb”, 由此可見windows 平臺的c 運行時MSVCRT 的memcpy 函數對重疊部分做了處理,同memmove 的實現。//notes: 如果重疊部分不做處理,應該輸出”aaaaaa”
下面我們用c 語言來實現memcpy 函數, 首先我們寫出不對內存重疊的處理函數,如下:
void *memcpy_no_handle_overlap (void *dest , void *src , unsigned int count )
{
?????? if ((NULL ==dest ) || (NULL ==src ))
????????????? return NULL ;
?
?????? char *d = (char *)dest ;
?????? char *s = (char *)src ;
?
?????? //Do normal (Upwards) Copy
?????? while (count -- > 0)
????????????? *d ++ = *s ++;
?????? return dest ;
}
測試程序如下:
int _tmain(int argc, _TCHAR* argv[])
{
?????? char s[16] = "aabbcc";
?????? char d[16] = {0};
??????
?????? memcpy_no_handle_overlap(s+2, s, 4);
?
?????? printf("%s", s);
?????? return 0;
}
輸出結果”aaaaaa”
下面討論處理memory overlapping 情況,如下圖:
判斷overlapping 條件如下:
If ( (dest <= src) ||??????????????? // green region 1
?? (dest >=src+count) )?????????? // green region 2
{
?????? // no memory overlapping
}
Else? // red region 3
{
?????? // there is overlapping
}
Overlapping 的處理:
我們可以看到memcpy_no_handle_overlap 函數,是從低地址依次賦值到高地址;在處理overlapping 時,如果我們采用同樣的方法( 低地址到高地址) ,高地址的值將會被覆蓋,所以我們應該從高地址依次到低地址賦值,如下圖:
?
? 函數代碼如下:
void *memcpy_handle_overlap(void *dest, void *src, unsigned int count)
{
?????? if ((NULL==dest) || (NULL==src))
????????????? return NULL;
?
?????? char *d = (char *)dest;
?????? char *s = (char *)src;
?
?????? //Check for overlapping buffers:
?????? if ( (d<=s) || (d>=s+count) )
?????? {?????
????????????? //Do normal (Upwards) Copy
????????????? while (count-- > 0)
???????????????????? *d++ = *s++;
?????? }
?????? else
?????? {
????????????? //Do Downwards Copy to avoid propagation
????????????? while (count > 0)
????????????? {
???????????????????? *(d+count-1) = *(s+count-1);
???????????????????? --count;
????????????? }
?
?????? }
?
?????? return dest;
}
測試代碼:
int _tmain(int argc, _TCHAR* argv[])
{
?????? char s[16] = "aabbcc";
?????? char d[16] = {0};
??????
?????? memcpy_handle_overlap(s+2, s, 4);
?
?????? printf("%s", s);
?????? return 0;
}
輸出結果為: “aaaabb “
?
最后測試代碼如下:
int _tmain(int argc, _TCHAR* argv[])
{
?????? char s[16] = "aabbcc";
?????? memcpy_no_handle_overlap(s+2, s, 4);
?????? printf("memcpy(ignore memory overlapping): %s/n", s);
?
?????? strcpy(s, "aabbcc");
?????? memcpy_handle_overlap(s+2, s, 4);
?????? printf("memcpy(handle memory overlapping): %s/n", s);
?
???? strcpy(s, "aabbcc");
?????? memcpy(s+2, s, 4);
?????? printf("memcpy( MSVCRT ): %s/n", s);
?
?????? strcpy(s, "aabbcc");
?????? memmove(s+2, s, 4);
?????? printf("memmove( MSVCRT): %s/n", s);
?
?????? return 0;
}
輸出結果為:
memcpy(ignore memory overlapping): aaaaaa
memcpy(handle memory overlapping): aaaabb
memcpy( MSVCRT ): aaaabb
memmove( MSVCRT): aaaabb
總結
以上是生活随笔為你收集整理的c语言实现memcpy的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电线一盘是95米还是100米?
- 下一篇: 怎么让晴天宝珠的掉落几率增加