C語言內存函數的具體使用
前言
上期我們學習了字符函數以及字符串函數,但是字符串函數僅僅只能對字符進行操作,那么這次我們來學習一下內存函數
在C語言中內存函數是一組用于內存操作的標準庫函數,它們定義在 <string.h>頭文件中,這些函數用于復制、設置、比較內存區(qū)域等,接下來我們來學習一下C語言中常用的內存函數。
1. memcpy 使?和模擬實現
memcpy與strcpy非常相似,但是strcpy只能對字符進行復制操作,而memcpy可以對任意類型的數據進行復制操作。
1.1 memcpy的使用

- 函數memcpy從source的位置開始向后復制num個字節(jié)的數據到destination指向的內存位置。
- 這個函數在遇到 '\0' 的時候并不會停下來。
- 如果source和destination有任何的重疊,復制的結果都是未定義的。
memcpy的使用:
#include<stdio.h>
#include<string.h>
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
memcpy(arr2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}運行結果:

可以這里的num參數為20, 表示從 arr1 復制20個字節(jié)的數據到 arr2中,因為這里復制的內容為整數,整形的大小占4個字節(jié),所以arr2從arr1中復制了前5個數字(也就是20個字節(jié)的數據)
1.2 memcpy模擬實現
既然知道了memcpy函數是如何使用的,那么我們接下來探索一下memcpy是如何實現的
#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memcpy(void* dst, const void* src, size_t num)
{
void* ret = dst;
assert(dst);
assert(src);
while (num--) {
*(char*)dst = *(char*)src;
dst = (char*)dst + 1;
src = (char*)src + 1;
}
return(ret);
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
my_memcpy(arr2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}運行結果:

我們可以看見模擬實現的my_memcpy函數與上面使用的memcpy函數的運行結果是一樣的
從中memcpy的前兩個形參使用的是void *類型來接收的,void *類型不能進行解引用和加減運算,所以在解引用和加減運算之前需要強制轉換成char *類型進行操作
函數的返回值是void*類型,返回的是目標地址,所以在進行指針運算前,我們需要先創(chuàng)建一個指針(ret)存儲目標地址,當復制操作完成后,返回目標地址
注意這里的dst和src是指針變量,所以在使用前用assert斷言判斷一下是否為NULL(空指針),并且因為src指針指向的數據是不能被修改的,所以這里用const進行修飾。
注意:memcpy只負責處理內存不重疊的情況,對于重疊內存拷貝使用memmove
2. memmove 使?和模擬實現
memmove函數的參數與memcpy函數是一樣的

- 和memcpy的差別就是memmove函數處理的源內存塊和?標內存塊是可以重疊的。
- 如果源空間和?標空間出現重疊,就得使?memmove函數處理。
2.1 memmove的使用
#include<stdio.h>
#include<string.h>
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr1 + 2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}運行結果:

那么為什么memmove函數能夠處理內存重疊的情況呢?接下來我們來模擬實現一下memmove函數。
2.2 memmove模擬實現
#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memmove(void* dst, const void* src, size_t count)
{
void* ret = dst;
if (dst <= src || (char*)dst >= ((char*)src + count))
{
while (count--)
{
*(char*)dst = *(char*)src;
dst = (char*)dst + 1;
src = (char*)src + 1;
}
}
else
{
dst = (char*)dst + count - 1;
src = (char*)src + count - 1;
while (count--)
{
*(char*)dst = *(char*)src;
dst = (char*)dst - 1;
src = (char*)src - 1;
}
}
return(ret);
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr1 + 2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}memmove的模擬實現與memcpy是相似的,但是這里需要分為兩種情況討論:
1. 目標地址>源內存地址
如果目標地址 > 源內存地址,那么我們就需要將數據從后向前進行拷貝,如果從前向后進行拷貝就會發(fā)生下面的現象

當我們從后面向前拷貝就不會出現這種現象:

2. 目標地址<源內存地址
如果目標地址 < 源內存地址,那么我們就需要將數據從前向后進行拷貝

3. 目標地址=源內存地址
當目標地址=源內存地址時,既可以使用從前向后的方式拷貝也可以使用從后向前的方式拷貝。
3. memset 函數的使?
memset是?來設置內存的,將內存中的值以字節(jié)為單位設置成想要的內容。

- ptr表示更改的起始地址
- value表示更改的內容
- num表示更改的字節(jié)數
memset的使用:
int main()
{
char str[] = "hello world";
memset(str, 'x', 6);
printf(str);
return 0;
}運行結果:

memset函數將str數組中的前6個字節(jié)的數據更改成了 ’x‘
4.memcmp 函數的使用

memcmp是用于比較兩塊內存
將指針 1 所指內存塊的前 num 個字節(jié)與指針 2 所指內存塊的前num個字節(jié)進行比較,如果它們完全匹配,則返回零,否則返回一個不等于零的值,表示哪個更大。
返回值如下:

memcmp函數的使用:

這里我們比較的是兩個整形數組前4個數據的大小, 一個整形的大小為4個字節(jié),所以比較的是16個字節(jié)數據的大小,arr前16個字節(jié)的數據<arr2前16個字節(jié)的數據,所以返回值為-1。
結語
那么以上就是C語言中常用的內存函數,學完內存函數后,對于復制、設置、比較等操作就不僅僅只局限在字符中了,也可以對任意類型的數據進行復制、設置、比較等操作。到此這篇關于C語言內存函數的具體使用的文章就介紹到這了,更多相關C語言內存函數內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
VisualStudio Community2019在安裝的過程中無法進入安裝界面的解決方法
這篇文章主要介紹了VisualStudio Community2019在安裝的過程中無法進入安裝界面的解決方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-03-03
Qt6 QML實現DateTimePicker組件的示例代碼
本文展示了基于Qt6.10實現的DateTimePicker時間日期選擇器組件,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2025-12-12

