九章算法系列(一)

問題:實現一個Memcpy函數

函數簡介:c和c++使用的內存拷貝函數,memcpy函數的功能是從源src所指的內存地址的起始位置開始拷貝n個字節到目標dest所指的內存地址的起始位置中。


本題主要考慮兩點:1)內存重疊與否2)重疊內存的copy方式

無重疊的內存copy:

void *mymemcpy(void *dst,const void *src,size_t num)
{
       if(NULL == dst || NULL == src){
       return NULL;
       }
       if(des>=src+num||src>dst+num){
	byte * psrc = (byte *)src;//byte 既爲unsigned char類型
	byte * pdst = (byte *)dst;
	while(num-->0)*pdst++ = *psrc++;
       }
       return dst;
}

內存重疊的copy:(依據源地址與目的地址的相對位置設計copy方式)

<pre name="code" class="cpp" style="color: rgb(51, 51, 51); font-size: 14px; line-height: 25.2px;">void * mymemcpy(void *dest, const void *src, size_t count)
{
    if (dest == NULL || src == NULL)
          return NULL;
    char *pdest = static_cast <char*>(dest);
    const char *psrc  = static_cast <const char*>(psrc);
    int n = count;
    if (pdest > psrc && pdest < psrc+count)
    {
        for (size_t i=n-1; i != -1; --i)
        {
                pdest[i] = psrc[i];//高到低
        }
    }
    else
    {
        for (size_t i= 0; i < n; i++)
        {
                pdest[i] = psrc[i];//低到高
        }
    }
    return dest;
}

對於內存重疊的copy基於src與dst的相對位置,可能會有人不太清楚,這裏給出我自己畫的圖



此外,給出有關void*的深入理解,也有助於本題的解決,有興許的朋友可以看一下

void的含義
void即“無類型”,void *則爲“無類型指針”,可以指向任何數據類型。

void指針使用規範
void指針可以指向任意類型的數據,亦即可用任意數據類型的指針對void指針賦值。例如:
int *pint;
void *pvoid;
pvoid = pint; /* 不過不能 pint = pvoid; */
如果要將pvoid賦給其他類型指針,則需要強制類型轉換如:pint = (int *)pvoid;


在ANSI C標準中,不允許對void指針進行算術運算如pvoid++或pvoid+=1等,而在GNU中則允許,因爲在缺省情況下,GNU認爲void *與char *一樣。sizeof( *pvoid )== sizeof( char ).

void的作用
對函數返回的限定。
對函數參數的限定。
當函數不需要返回值時,必須使用void限定。例如: void func(int, int);
當函數不允許接受參數時,必須使用void限定。例如: int func(void)。


由於void指針可以指向任意類型的數據,亦即可用任意數據類型的指針對void指針賦值,因此還可以用void指針來作爲函數形參,這樣函數就可以接受任意數據類型的指針作爲參數。例如:
void * memcpy( void *dest, const void *src, size_t len );
void * memset( void * buffer, int c, size_t num );


發佈了195 篇原創文章 · 獲贊 194 · 訪問量 67萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章