欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言深入詳解四大內存函數的使用

 更新時間:2022年07月07日 08:53:18   作者:龍兆萬  
這篇文章主要介紹了C語言的四大內存函數,講解了mencpy、memmove、memcmp、memset函數,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步

1.memcpy

與字符串函數 strcpy 類似,也是進行拷貝。但是需要注意的是,strcpy 是針對字符串進行拷貝,而 memcpy 是針對內存進行拷貝。

如何理解呢?strcpy 進行拷貝的時候,只能一個字節(jié)一個字節(jié)的拷貝,但要實現 整型、浮點型等數據類型拷貝的時候,就不得不用到 memcpy 了。

我們觀察 strcpy 的函數聲明:

char * strcpy ( char * destination, const char * source );

再觀察 memcpy 的函數聲明:

void * memcpy ( void * destination, const void * source, size_t num );

可以看到 strcpy 的局限在于只能接收 字符型 的指針,但 memcpy 對于類型可以在函數內部實現自定義。

我們?yōu)g覽cplusplus對參數作出的解釋:

現在我們要研究如何使用:

#include <stdio.h>
#include <string.h>
int main()
{
	int dest[10] = { 0 };
	int src[10] = { 1,2,3,4,5,6,7,8,9,10 };
	memcpy(dest, src, 20);//拷貝 20 個字節(jié)
	return 0;
}

我們從 src 數組中,拷貝 20 個字節(jié)的數據放到 dest 數組中。那么我們通過 調試—窗口—監(jiān)視來觀察 dest 數組中的變化:

未經 memcpy 前:

經 memcpy 后:

可以直觀地看到, dest 數組中前 20 個字節(jié)的內容發(fā)生了改變。

使用起來倒是不復雜,那我們能不能用自己的代碼去模擬實現一個 memcpy 函數?

#include <stdio.h>
void* AnalogMemcpy(void* dest, const void* src, unsigned int num)
{
	void* start = dest;//定義一個記錄 dest 初始地址的指針
	while (num--)//一個字節(jié)一個字節(jié)拷貝
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return start;//返回此指針
}
int main()
{
	int dest[10] = { 0 };
	int src[10] = { 1,2,3,4,5,6,7,8,9,10 };
	AnalogMemcpy(dest, src, 20);
	return 0;
}

我們的實現思路非常簡單,因為官方給出第三個參數的定義是:要復制的字節(jié)數。那我們順水推舟一個字節(jié)一個字節(jié)的拷貝。

但是到這里,可能會存在這樣一個問題: char 類型是一個字節(jié),我們使用 memcpy 時也是一個字節(jié)一個字節(jié)的拷貝,那為什么 strcpy 不能拷貝整型?

在我們自己模擬實現 strcpy 的時候,拷貝的停止條件是什么?是 src 字符串碰到 '\0' 。默認我們的設備是小端存儲模式,那么我們使用 strcpy 進行拷貝的時候就會出現這種情況:

現在我們使用模擬實現的 memcpy 函數來執(zhí)行這段代碼:

#include <stdio.h>
void* AnalogMemcpy(void* dest, const void* src, unsigned int num)
{
	void* start = dest;//定義一個記錄 dest 初始地址的指針
	while (num--)//一個字節(jié)一個字節(jié)拷貝
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return start;//返回此指針
}
int main()
{
	int dest[10] = { 1,2,3,4,5,6,7,8,9,10 };
	AnalogMemcpy(dest + 3, dest, 20);
	return 0;
}

這段代碼的意思是這樣的:

但事實上真正的結果是:

這該如何解釋呢?其實不難:

那么我們暫且定下一個結論:

memcpy 只能處理空間不重疊的數據拷貝。

2.memmove

這個函數與 memcpy 的功能相同,都是進行數據拷貝。但是不同的點是:memmove 是用來處理空間重疊的數據拷貝的。

這是 memmove 的函數聲明:

void * memmove ( void * destination, const void * source, size_t num );

既然是處理空間重疊的情況,那我們直接對上一個代碼進行處理:

可以看到, memmove 符合我們的預期實現了效果。

我們現在來挑戰(zhàn)一下如何模擬實現一個 memmove 函數:

#include <stdio.h>
void* AnalogMemmove(void* dest, const void* src, unsigned int num)
{
	void* start = dest;//定義一個記錄 dest 初始地址的指針
 
	if (src < dest)//如果 src 在 dst 的左邊
	{
		while (num--)
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
	else
	{
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	return start;//返回這個指針
}
int main()
{
	int dest[10] = { 1,2,3,4,5,6,7,8,9,10 };
	AnalogMemmove(dest + 3, dest, 20);
	return 0;
}

乍一看,這個代碼比較復雜,事實上,只有兩種情況。

我們來分析一下:

但是!這里要注意了,上面使使用自己模擬的 memcpy 不能實現空間重疊拷貝的,但庫函數原裝的 memcpy 能夠實現空間重疊拷貝嗎?

我們來看庫函數 memcpy 能否實現空間重疊拷貝:

#include <stdio.h>
#include <string.h>
int main()
{
	int dest[10] = { 1,2,3,4,5,6,7,8,9,10 };
	memcpy(dest + 3, dest, 20);
	return 0;
}

這就奇了怪了!既然庫函數 memcpy 能夠實現空間重疊的拷貝,那還需要 memmove 做什么?

事實上,對于我使用的 Visual Studio 2022 這款編譯器來說,memcpy 是可以實現空間重復拷貝的。也就是說可能在其他的編譯器上實現不了空間重疊拷貝,但 Visual Studio 2022 這款編譯器賦予了 memcpy 這項功能。

3.memcmp

與 strcmp 類似的,這個函數也是進行比較的函數,我們觀察一下它的函數聲明:

int memcmp ( const void * ptr1, const void * ptr2, size_t num );

那么對于這些參數以及返回值的解釋是:

因為我們學習過 strcmp ,那我們現在直接使用它:

#include <stdio.h>
#include <string.h>
int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 1,2,3,3,4,5,6,7,8,9 };
	int ret=memcmp(arr1, arr2, 20);
	if (ret > 0)
		printf("arr1 > arr2\n");
	else if (ret < 0)
		printf("arr1 < arr2\n");
	else
		printf("arr1 == arr2\n");
	return 0;
}

與 strcmp 的原理是一致的,這里就不贅述了。

4.memset

直譯過來就是內存設置。事實上也是這么回事。

觀察它的函數聲明:

void * memset ( void * ptr, int value, size_t num );

它的作用是以及參數的意義:

說白了就是:你需要提供一個指針,這個指針指向的要被填充的內存。然后提供一個值,這個值決定了每個字節(jié)要被填充為什么內容。最后提供一個數,這個數指的是你要填充多少個字節(jié)。

我們寫一個例子:

#include <stdio.h>
#include <string.h>
int main()
{
	int arr[10] = { 0 };
	memset(arr, 1, 4);
	return 0;
}

這就奇了怪了,我們不是設置四個字節(jié)為 1 嗎?千萬不要么想。我們上面強調過了,這個函數是對每個字節(jié)填充。

我們分析一下我們寫的例子:

到此這篇關于C語言深入詳解四大內存函數的使用的文章就介紹到這了,更多相關C語言內存函數內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C++讀取配置文件的示例代碼

    C++讀取配置文件的示例代碼

    這篇文章主要介紹了C++讀取配置文件的示例代碼,幫助大家更好的理解和學習C++開發(fā),感興趣的朋友可以了解下
    2020-08-08
  • C語言實現進程間通信原理解析

    C語言實現進程間通信原理解析

    這篇文章主要介紹了C語言實現進程間通信原理解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-06-06
  • C++中fork函數的使用及原理

    C++中fork函數的使用及原理

    這篇文章主要介紹了C++中fork函數的使用及原理,在C++中,fork函數用于創(chuàng)建一個新的進程稱為子進程,該進程與原始進程幾乎完全相同,需要的朋友可以參考下
    2023-05-05
  • c++將vector迭代器轉換為指針的實現方式

    c++將vector迭代器轉換為指針的實現方式

    這篇文章主要介紹了c++將vector迭代器轉換為指針的實現方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • C語言中的const如何保證變量不被修改

    C語言中的const如何保證變量不被修改

    這篇文章主要給大家介紹了關于C語言中const如何保證變量不被修改的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • c++定義全局變量詳解

    c++定義全局變量詳解

    這篇文章主要給大家介紹了C++語言中定義全局變量,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。
    2021-10-10
  • C++中std::ios_base::floatfield報錯已解決

    C++中std::ios_base::floatfield報錯已解決

    在C++編程中,設置浮點數輸出格式時可能遇到std::ios_base::floatfield錯誤,解決方法包括使用正確的格式化標志組合,避免沖突的格式化設置,以及檢查流狀態(tài)標志是否正確,通過這些方法可以有效避免浮點數格式化錯誤,并確保輸出精確
    2024-09-09
  • C++容器算法示例詳解

    C++容器算法示例詳解

    在談到容器算法,我們大概率會用到謂詞predicate,謂詞返回的類型是布爾類型(bool)可以是lambda表達式、函數對象以及其它可調用的對象,這篇文章主要介紹了C++容器算法,需要的朋友可以參考下
    2024-08-08
  • C++實現簡單的計算器小功能

    C++實現簡單的計算器小功能

    這篇文章主要為大家詳細介紹了C++實現簡單的計算器小功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C語言實現隨機抽取紙牌程序

    C語言實現隨機抽取紙牌程序

    這篇文章主要為大家詳細介紹了C語言實現隨機抽取紙牌程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03

最新評論