1.memcpy
memcpy:拷貝字符到緩沖區
void* memcpy(void* dest,const void* src,size_t count);
注:count為拷貝位元組的個數
memcpy函式在實作的時候,不知道未來會被用來拷貝什么型別的資料,所以用void*的指標接收是比較合適的!
memcpy的模擬實作
//memcpy的模擬實作
#include<assert.h>
void* my_memcpy(void* dest,const void* src, size_t count)
{
assert(dest && src);
void* ret = dest;
while (count--)
{
*(char*)dest = *(char*)src;
((char*)dest)++;//空型別的指標不能++,所以強轉成char*指標,又因為++優先級較高,所以先括起來再++
((char*)src)++;
}
return ret;
}
int main()
{
int arr1[10] = { 1, 2, 3, 4, 5, 6 };
int arr2[20] = { 0 };
my_memcpy(arr2, arr1, 16);
return 0;
}
memcpy是用來拷貝不相關的記憶體塊的,若記憶體重疊,則無法拷貝!
重疊拷貝示例如下
//重疊拷貝
int main()
{
int arr[20] = { 1, 2, 3, 4, 5, 6, 7, 8, 9,10 };
memcpy(arr + 2, arr, 16);
return 0;
}
注:然而我們在vs下發現memcpy可以實作重疊拷貝(模擬實作的my_memcpy就不行),但標準規定中memcpy只用實作不重疊拷貝就行,因此重疊拷貝還是需要用memmove,
2.memmove
(可進行重疊拷貝)
//memmove函式(可實作重疊拷貝)
int main()
{
int arr[20] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
memmove(arr + 2, arr, 16);//memmove可重疊拷貝
return 0;
}

如圖所示
以指標src為分界線
若dest在src右邊,則從后向前拷貝
若dest在src左邊,則從前向后拷貝
若src和dest所指向的兩個記憶體塊不相關(不重疊),則拷貝順序無所謂
有了以上結論后,我們就可以模擬實作memmove,
memmove的模擬實作
//memmove模擬實作
void* my_memmove(void* dest, void* src, size_t count)
{
void* ret = dest;
if (dest < src)
{
//從前向后
while (count--)
{
*((char*)dest) = *((char*)src);
}
}
else
{
//從后向前
while (count--)
{
*((char*)dest + count) = *((char*)src + count);//此代碼傳進函式的count=16,第一次進入回圈后count=15,指標首地址加15剛好指向末尾
}
}
return ret;
}
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
my_memmove(arr + 2, arr, 16);
return 0;
}
3.memcmp
字符比較函式
int memcmp(const void* buf1,const void* buf2,size_t count);
注:count為要比較的位元組數
回傳結果:
<0 buf1 less than buf2
=0 buf1 identical to buf2
>0 buf1 greater than buf2
//memcmp函式(比較字符函式)
int main()
{
int arr1[] = { 1, 2, 3, 4, 5 };
int arr2[] = { 1, 2, 4, 6, 7 };
int ret = memcmp(arr1, arr2, 8);//比較位元組數為8,即比較前兩個數字,相等,所以回傳0
printf("%d\n", ret);
return 0;
}
int main()
{
int arr1[] = { 1, 2, 3, 4, 5 };//01 00 00 00 02 00 00 00 03 00 00 00
int arr2[] = { 1, 2, 4, 6, 7 };//01 00 00 00 02 00 00 00 04 00 00 00
int ret = memcmp(arr1, arr2, 9);
printf("%d\n", ret);//-1
return 0;
}
4.memset
//memset
int main()
{
char arr[10] = { 0 };
memset(arr, '*', 10);
return 0;
}

需要注意的是,這個函式第三個引數是位元組數,因為上面的例子是一個字符陣列,因此修改10個位元組剛好就將字符陣列中的10個元素改掉,來看看下面的易錯例子
//memset易錯例子
int main()
{
int arr[10] = { 0 };
memset(arr, 1, 40);
return 0;
}

按理來說,arr是個有10個元素的整型陣列,我們應該是把arr中的10個元素都改成了1,但是事實并非如此,我們看到每個元素都是很大的數,為什么呢,這是因為上面已經提到了,memset會把每個位元組都修改,因此記憶體中的每個元素應該是從00 00 00 00修改成01 01 01 01,將這個十六進制數0x01010101轉換成十進制后就會變成一個很大的數,
我們把這個很大的數進行16進制轉換可以看到

因此使用這個函式時要加倍小心,它會將每個位元組上的內容都修改!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/265502.html
標籤:其他
上一篇:Qt+opencv 配置教程
