亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C語言全部內(nèi)存操作函數(shù)的實現(xiàn)詳細講解

 更新時間:2021年02月26日 11:10:02   作者:貧僧愛用飄柔  
這篇文章主要介紹了C語言全部內(nèi)存操作函數(shù)的實現(xiàn)詳細講解,作者用圖文代碼實例講解的很清晰,有感興趣的同學(xué)可以研究下

memcpy內(nèi)存拷貝函數(shù)

void* memcpy(void* destination, const void* source, size_t num);
  • memcpy函數(shù)從source的位置開始向后拷貝num個字節(jié)的數(shù)據(jù)到destination的內(nèi)存位置
  • 這個函數(shù)在遇到\0的時候并不會停下來
  • 如果source和destination有任何的重疊,復(fù)制的結(jié)果都是未定義的

使用方法:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>

int main()
{
	char arr1[20] = { 0 };
	char arr2[] = "hello world!";
	int arr3[10] = { 0 };
	int arr4[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int i = 0;

	memcpy(arr1, arr2, 12);
	memcpy(arr3, arr4, 16);
	printf("%s\n", arr1);

	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr3[i]);
	}

	return 0;
}

輸出結(jié)果:


image-20210224094511895

如果源頭和目的地是同一塊內(nèi)存它進行拷貝的時候會出現(xiàn)覆蓋的情況。

如:

#include <stdio.h>
#include <string.h>

int main()
{
 int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
 int i = 0;
 
 memcpy(arr + 2, arr, 16);
 
 for (i = 0; i < 10; i++)
 {
 printf("%d ", arr[i]);
 }
 
 return 0;
}

image-20210224095909038

可以看到它并沒有如我們預(yù)期的輸出來輸出結(jié)果,我們預(yù)期的結(jié)果應(yīng)該是:1 2 1 2 3 4 7 8 9 10

可是memcpy拷貝的時候會覆蓋,而C語言對memcpy的標準是只要能實現(xiàn)拷貝即可,不考慮同一塊內(nèi)存拷貝會覆蓋的情況,這種情況是由另一個函數(shù)來處理。

當(dāng)然有些編譯器對memcpy函數(shù)的實現(xiàn)是有優(yōu)化過的,目前我個人知道的編譯器是VS它是對memcpy有優(yōu)化的,如果拷貝的是同一塊內(nèi)存它不會覆蓋,而是如預(yù)期的那樣進行拷貝。

memcpy函數(shù)的實現(xiàn)

#include <assert.h>

void* my_memcpy(void* dest, const void* src, unsigned int count)
{
	assert(dest && src);//斷言
	void* temp = dest;//temp保存dest的起始地址

	while (count--)
	{
		*(char*)dest = *(char*)src;//復(fù)制src的內(nèi)容到dest
		++(char*)dest;//下一個字節(jié)的拷貝
		++(char*)src;
	}

	return temp;//返回dest起始地址
}

void* my_memcpy(void* dest, const void* src, unsigned int count);

參數(shù)一:void* dest

  • dest設(shè)置成空類型,因為空類型可以接收任何大小的數(shù)據(jù),但是有一個缺陷它不能自增或者自減,也不能直接解引用因給它空類型是一個沒有具體類型,它不知道它能訪問多少個字節(jié),所以使用空類型的時候我們需要強制類型轉(zhuǎn)換。
  • dest是緩沖區(qū)

參數(shù)二:void* src

  • 它的類型和dest一樣不過,它和參數(shù)一不同的是它被const保護起來了,因為它只是被復(fù)制也就是說我們只是訪問它里面的內(nèi)容并不需要修改它,所以我們就加一個const把它保護起來,防止我們不小心對它進行修改

參數(shù)三:unsigned int counst

  • counst是我們要修改多少字節(jié)的參數(shù),修改是以字節(jié)為單位的,它的類型是unsigned int (無符號整整形)也就是說不能出現(xiàn)負數(shù)

返回類型:void*

  • 返回dest的首地址

assert(dest && src)這個是用來保證代碼的健壯性,assert()函數(shù)是斷言,如果傳過來的是空指針,那么就是假因為NULL的值是0,只有兩邊都為真才不會有提示。

*(char*)dest = *(char*)src因為是void* 類型所以我們要強制轉(zhuǎn)換才能解引用進行拷貝操作,而我們要操作的是一個字節(jié)所以轉(zhuǎn)為字符型指針最合適。

++(char*)dest;和上面的同理,要強制類型轉(zhuǎn)換才能進行++和–操作。


memmvoe函數(shù)

void* memmove(void* destination, const void* source, size_t num);
  • 和memcpy的差別就是memmove函數(shù)處理的源內(nèi)存塊和目標內(nèi)存塊是可以重疊的。
  • 如果源空間和目標空間出現(xiàn)重疊,就得使用memmove函數(shù)處理

使用方法:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <assert.h>

int main()
{
	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int i = 0;

	memmove(arr + 2, arr, 16);

	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}

	return 0;
}

memmovememcpy的使用方法一樣,沒什么大區(qū)別。

memmove函數(shù)的實現(xiàn)

#include <assert.h>

void* my_memmove(void* dest, const void* src, unsigned int count)
{
	assert(dest && src);//斷言
	void* temp = dest;

	if (dest < src)//小于src從前向后
	{
		while (count--)
		{
			*(char*)dest = *(char*)src;
			++(char*)dest;
			++(char*)src;
		}
	}
	else//大于從后向前
	{
		while (count--)
		{
			*((char*)dest + count) = *((char*)src + count);
		}
	}

	return temp;
}

為了處理同塊內(nèi)存的拷貝,這里我們分為了兩種方法。

  1. 從前向后拷貝
  2. 從后向后拷貝

memcpy用的是從前向后拷貝,所以會出現(xiàn)被覆蓋的情況。

那么問題來了,我們什么情況才從前向后拷貝和從后向前拷貝呢?

image-20210224105035626

我們可以以src為分界線,如果dest小于src我們就從前向后,這樣就避免了src的內(nèi)容被覆蓋之后被拷貝到dest里面去,如果dest大于src,我們就從后向前。

那有人問如果等于呢?等于的話你從前向后還是從后向前不都一樣?

所以按照這個思路我們寫成兩個拷貝順序,從后向前我們不用思考了,想在我們只需要思考從后向前拷貝。

	while (count--)
		{
			*((char*)dest + count) = *((char*)src + count);
		}

從后向前我們只需要先得到dest和src末尾的地址就能進行從后向前操作了,count + dest不就得到了末尾了嗎?counst + dest得到末尾的\0的地址,但是我們不需要修改\0所以count + dest之前我們對count自減。

后面就不需要dest自減的操作了,因為count每次減一我們就得到前面一個的地址,當(dāng)count減完了,我們也拷貝完了。

memcmp內(nèi)存塊比較函數(shù)

int memcmp(const void* ptr1, const void* ptr2, size_t num);
  • 比較從ptr1和ptr2指針開始的num個字節(jié)
  • 返回值,當(dāng)ptr1大于ptr2就返回大于1的值,當(dāng)ptr1小于ptr2就返回小于0的值,當(dāng)?shù)扔诘臅r候返回0

使用案列:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <assert.h>

int main()
{
	char arr1[] = "abcz";
	char arr2[] = "abcd";

	if ( 0 < memcmp(arr1, arr2, 4))
	{
		printf("大于\n");
	}
	else if(0 > memcmp(arr1, arr2, 4))
	{
		printf("小于\n");
	}
	else
	{
		printf("等于\n");
	}

	return 0;
}

memcpy函數(shù)的實現(xiàn)

#include <assert.h>

int my_memcmp(void* dest, const void* src, unsigned int count)
{
	assert(dest && src);//斷言

	if (!count)
	{
		return 0;
	}

	while (--count && *(char*)dest == *(char*)src)
	{
		++(char*)dest;
		++(char*)src;
	}

	return *(char*)dest - *(char*)src;
}
	if (!count)
	{
		return 0;
	}

如果count是0的話就直接返回0

while (count-- && *(char*)dest == *(char*)src)
	{
		++(char*)dest;
		++(char*)src;
	}

當(dāng)count個數(shù)比較完或者dest不等于src,我們就停止循環(huán)。

return *(char*)dest - *(char*)src;

直接返回dest - src,如果它們兩相等一定返回0,dest小于src返回的是小于0的值,大于則返回大于0的值。

memset修改內(nèi)存塊

void *memset( void *dest, int c, size_t count )
  • dest是目的
  • 地第二個修改成什么?
  • 第三個修改內(nèi)存的個數(shù)

memset是以1字節(jié)為單位來修改,第二個參數(shù)是要修改成什么字符,第三個參數(shù)是修改內(nèi)存?zhèn)€數(shù)以1字節(jié)為單位

使用案列:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>

int main()
{
	char arr[10] = { 0 };
	int i = 0;

	memset(arr, '6', 10);

	for (i = 0; i < 10; i++)
	{
		printf("arr[%d]=%c\n", i, arr[i]);
	}

	return 0;
}

memset函數(shù)實現(xiàn)

#include <assert.h>

void* my_memset(void* dest, int a, unsigned int count)
{
	assert(dest);//斷言
	void* temp = dest;//記錄dest的首地址

	while (count--)
	{
		*(char*)dest = a;
		++(char*)dest;
	}

	return temp;//返回dest的首地址
}
while (count--)
{
	*(char*)dest = a;
	++(char*)dest;
}

把a的值給dest,來進行修改,每次修改一個字節(jié)就自增一修改下個字節(jié)。

到此這篇關(guān)于C語言全部內(nèi)存操作函數(shù)的實現(xiàn)詳細講解的文章就介紹到這了,更多相關(guān)C語言內(nèi)存操作函數(shù)的實現(xiàn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解C語言中的函數(shù)、數(shù)組與指針

    詳解C語言中的函數(shù)、數(shù)組與指針

    這篇文章主要介紹了C語言中的函數(shù)、數(shù)組與指針,本文給大家介紹的非常詳細,具有參考借鑒價值,需要的朋友可以參考下
    2017-02-02
  • VC創(chuàng)建DLL動態(tài)鏈接庫的方法

    VC創(chuàng)建DLL動態(tài)鏈接庫的方法

    這篇文章主要介紹了VC創(chuàng)建DLL動態(tài)鏈接庫的方法,實例分析VC創(chuàng)建動態(tài)鏈接庫的完整步驟,需要的朋友可以參考下
    2015-05-05
  • C語言實現(xiàn)反彈球小游戲

    C語言實現(xiàn)反彈球小游戲

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)反彈球小游戲,利用函數(shù)寫的C語言小游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • C語言超詳細講解結(jié)構(gòu)體與聯(lián)合體的使用

    C語言超詳細講解結(jié)構(gòu)體與聯(lián)合體的使用

    結(jié)構(gòu)體和聯(lián)合體用于描述事物的屬性,如一只鳥的信息,可能包括它的品種,體重,顏色,年齡等,接下來大家一起來詳細看看吧
    2022-05-05
  • 新手向超詳細的C語言實現(xiàn)動態(tài)順序表

    新手向超詳細的C語言實現(xiàn)動態(tài)順序表

    本文主要介紹了C語言實現(xiàn)動態(tài)順序表,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • C++插件化 NDD源碼的插件機制實現(xiàn)解析

    C++插件化 NDD源碼的插件機制實現(xiàn)解析

    這篇文章主要介紹了C++插件化 NDD源碼的插件機制實現(xiàn)解析,這里再介紹推薦下優(yōu)秀的國產(chǎn)軟件開源項目?NDD(notepad--),一個支持windows/linux/mac的文本編輯器,目標是要國產(chǎn)替換同類軟件,需要的朋友可以參考下
    2023-03-03
  • C++中的三種繼承public,protected,private詳細解析

    C++中的三種繼承public,protected,private詳細解析

    我們已經(jīng)知道,在基類以private方式被繼承時,其public和protected成員在子類中變?yōu)閜rivate成員。然而某些情況下,需要在子類中將一個或多個繼承的成員恢復(fù)其在基類中的訪問權(quán)限
    2013-09-09
  • C++ 結(jié)構(gòu)體初始化與賦值詳解

    C++ 結(jié)構(gòu)體初始化與賦值詳解

    本文主要介紹了C++ 結(jié)構(gòu)體初始化與賦值詳解,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • C++實現(xiàn)LeetCode(48.旋轉(zhuǎn)圖像)

    C++實現(xiàn)LeetCode(48.旋轉(zhuǎn)圖像)

    這篇文章主要介紹了C++實現(xiàn)LeetCode(48.旋轉(zhuǎn)圖像),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • Qt+OpenCV實現(xiàn)目標檢測詳解

    Qt+OpenCV實現(xiàn)目標檢測詳解

    這篇文章主要介紹了如何利用Qt和OpenCV中自帶xml文件實現(xiàn)目標檢測,文中的實現(xiàn)過程講解詳細,感興趣的小伙伴可以動手試一試
    2022-03-03

最新評論