搞懂內存函數

引言

本文介紹memcpy的使用和模擬實現、memmove的使用和模擬實現、memcmp使用、memset使用

?158c3f50b199454985017a51dbef9841.png? ? ? ? ? ? ? ???豬巴戒:個人主頁?

???????????????所屬專欄:《C語言進階》

? ? ? ? 🎈跟著豬巴戒,一起學習C語言🎈

目錄

引言

memcpy

memcpy的使用

memcpy的模擬實現

memmove

memcpy函數不用來處理重疊的內存的數據拷貝:

memmove的模擬實現

?總結:

?模擬實現代碼

memcmp

memset


memcpy

void * memcpy ( void * destination, const void * source, size_t num )
  • memcpy的作用就是將source的內容拷貝到destination
  • num說明了拷貝多少個字節
  • 返回值是destination.

memcpy的使用

#include<stdio.h>
#include<string.h>
int main()
{int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[20] = { 0 };memcpy(arr2, arr1, 20);int i = 0;for (i = 0; i < 5; i++){printf("%d ", arr2[i]);}return 0;
}

5832dc2659294508bad478215341d1aa.png?


memcpy的模擬實現

?內存函數就是無論是什么類型的數據都可以使用。

void* ,屬于通用類型的指針,可以存放任意類型的地址。

assert,斷言,保證dest和source不是空指針。

num是需要拷貝的字節數。

通過將地址轉化為(char*)的形式,將需要拷貝的內容一個字節一個字節地將它們拷貝,就可以實現各種數據的拷貝。

然后dest轉移到下一個字節,source轉移到下一個字節,知道拷貝完num個字節算結束。

#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* source, size_t num)
{assert(dest && source);void* start = dest;while (num--){*(char*)dest = *(char*) source;dest = (char*)dest + 1;source = (char*)source + 1;}return start;
}


memmove

void * memmove ( void * destination, const void * source, size_t num )
  • 和memcpy的差別就是memmove函數處理的源內存塊和?標內存塊是可以重疊的。
  • 參數和memcpy是一樣的。?

memcpy函數不用來處理重疊的內存的數據拷貝:

將arr1數組改成{1,2,1,2,3,4,5,8,9,10},從第三位元素開始,拷貝自己的第一到第五個元素

#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* source, size_t num)
{assert(dest && source);void* start = dest;while (num--){*(char*)dest = *(char*) source;dest = (char*)dest + 1;source = (char*)source + 1;}return start;
}
int main()
{int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };my_memcpy(arr1 + 2, arr1, 20);int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr1[i]);}return 0;
}

70351ed1ff4a4ba599115e7b0678b91b.png?

memcpy在重疊內存拷貝的時候,第三個元素被改成1,第四個元素被改成2,

而第五個元素本來是應該賦值為3的,但是第三個元素已經被改成1了。

第六個元素本來是由第四個元素重新賦值,但是第四個元素被改成了2.

39380881c7a64356adb8af265f088548.png?

memmove的模擬實現

如果說我們要將紅色部分拷貝到藍色部分

從前向后拷貝不行,我們要將紅色的部分拷貝到藍色的部分,先將第一個元素拷貝到第三個元素,紅色區域的內存被改變,等到將第三個元素拷貝到第五個元素的時候,第三個元素已經發生改變。

從后向前拷貝,如果我們可以先將第五個元素拷貝到第七個元素,這樣紅色的三、四、五元素先拷貝完后被改變就可以把數值3,4,5成功傳到第五、六、七個元素。

25c5324f1eb04ea586499ddf3238b85c.png?

?這一次,

從后向前拷貝不行,我們要將紅色部分拷貝到藍色的部分,先將第七個元素拷貝到第五個元素,首先改變了第五個元素的內容,到時候第五個元素還要對第三個元素進行拷貝。

從前向后拷貝,如果我們先將第三個元素拷貝到第一個元素,等輪到第三個元素進行拷貝的時候,第三個元素里的內容已經轉出去了,轉到第一個元素了,那么第三個元素的內容就可以隨便修改了。

ce3a5a681399471bb10ed37671736832.png?

?總結:

為了保證source中的數據在拷貝之前就被修改,

  • 當dest在source的右邊的時候,采用從后向前的方式
  • 當dest在source的左邊的時候,采用從前向后的方式

?模擬實現代碼

#include<stdio.h>
#include<assert.h>
void* my_memmove(void* dest, const void* source, size_t num)
{assert(dest && source);void* start = dest;if (dest < source){//從前向后while (num--){*(char*)dest = *(char*)source;dest = (char*)dest + 1;source = (char*)source + 1;}}else{//從后向前拷貝while (num--){*((char*)dest + num) = *((char*)source + num);}}return start;
}

memcmp

可以比較任意類型的數據

int memcmp ( const void * ptr1, const void * ptr2, size_t num )
  • ptr1指向的第一個空間
  • ptr2指向的第二塊空間
  • ptr1和ptr2之間的內存比較
  • num表示需要比較的字節大小

63c51fcf34ab485697e73736e1b3cf45.png?


?arr1和arr2比較,arr1比arr2小,返回小于0的數值。

int main()
{int arr1[] = { 1,2,3,4,5 };int arr2[] = { 1,3,2 };int ret = memcmp(arr1, arr2, 12);printf("%d", ret);return 0;
}

7da67d9fc3684a7ab9f8ec3fd30040bb.png??


memset

void * memset ( void * ptr, int value, size_t num )
  • ptr需要填充的地址空間
  • value,填充什么字符
  • num,填充幾個字節
#include<stdio.h>
#include<string.h>
int main()
{char arr[] = "hello world";memset(arr, 'x', 5);printf("%s\n", arr);return 0;
}

92ad5e3e260e4e8988224f64fb739406.png?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/209626.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/209626.shtml
英文地址,請注明出處:http://en.pswp.cn/news/209626.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

JS加密/解密之HOOK實戰2

上一篇文章介紹了HOOK常規的應用場景&#xff0c;這篇我們講一下HOOK其他原生函數。又是一個新的其他思路 很多時候&#xff0c;當我們想要某些網站的請求參數的時候&#xff0c;因為某些加密導致了獲取起來很復雜。 這時候hook就十分方便了 源代碼 var _JSON_Parse JSON.…

scp 指令詳細介紹

目錄 1. 基本語法 2. 例子 從本地到遠程 從遠程到本地 從遠程到遠程 使用端口和指定私鑰 遞歸復制目錄 3. 注意事項 如何拷貝文件的軟鏈接 SCP&#xff08;Secure Copy Protocol&#xff09;是一種用于在計算機之間安全地傳輸文件的協議。它通過加密的方式在網絡上安全…

Vue:Vue的開發者工具不顯示Vue實例中的data數據

一、情況描述 代碼&#xff1a; 頁面&#xff1a; 可以看到&#xff0c;input獲取到了data數據&#xff0c;但是&#xff0c;vue-devtool沒有獲取到data數據 二、解決辦法 解決辦法1&#xff1a; data.name的值不能全是中文&#xff0c;比如改成aa尚硅谷 解決辦法2&…

C語言 編程題

C語言學習&#xff01; 1.小明上課需要走n階臺階&#xff0c;他每次可以選擇走一階或者走兩階&#xff0c;他一共有多少種走法&#xff1f; 輸入描述&#xff1a;輸入包含一個整數n&#xff08;1 ≤ n ≤30&#xff09; 輸出描述&#xff1a;輸出一個整數&#xff0c;即小明可…

LeetCode 1457. 二叉樹中的偽回文路徑||位運算 DFS

1457. 二叉樹中的偽回文路徑 給你一棵二叉樹&#xff0c;每個節點的值為 1 到 9 。我們稱二叉樹中的一條路徑是 「偽回文」的&#xff0c;當它滿足&#xff1a;路徑經過的所有節點值的排列中&#xff0c;存在一個回文序列。 請你返回從根到葉子節點的所有路徑中 偽回文 路徑的…

Golang優雅實現按比例切分流量

我們在進行灰度發布時&#xff0c;往往需要轉發一部分流量到新上線的服務上&#xff0c;進行小規模的驗證&#xff0c;隨著功能的不斷完善&#xff0c;我們也會逐漸增加轉發的流量&#xff0c;這就需要按比例去切分流量&#xff0c;那么如何實現流量切分呢&#xff1f; 我們很容…

力扣(LeetCode)-1. 兩數之和

給定一個整數數組 nums 和一個整數目標值 target&#xff0c;請你在該數組中找出 和為目標值 target 的那 兩個 整數&#xff0c;并返回它們的數組下標。 你可以假設每種輸入只會對應一個答案。但是&#xff0c;數組中同一個元素在答案里不能重復出現。 你可以按任意順序返回…

【交流】PHP生成唯一邀請碼

目錄 前言&#xff1a; 1.隨機生成&#xff0c;核對user表是否已存在 代碼&#xff1a; 解析&#xff1a; 缺點&#xff1a; 2.建表建庫&#xff0c;每次從表中隨機抽取一條&#xff0c;用完時擴充 表結構 表視圖 代碼 解析 缺點 結論&#xff1a; 前言&#xff1a; …

LinuxBasicsForHackers筆記 -- 壓縮和歸檔

壓縮分為有損或無損。有損壓縮對于減小文件大小非常有效&#xff0c;但會丟失信息的完整性。換句話說&#xff0c;壓縮后的文件與原始文件并不完全相同。 這種類型的壓縮非常適合圖形、視頻和音頻文件&#xff0c;文件中的微小差異幾乎不會被注意到。 本章重點介紹這種無損壓縮…

解讀Stable Video Diffusion:詳細解讀視頻生成任務中的數據清理技術

Diffusion Models視頻生成-博客匯總 前言:Stable Video Diffusion已經開源一周多了,技術報告《Stable Video Diffusion: Scaling Latent Video Diffusion Models to Large Datasets》對數據清洗的部分描述非常詳細,雖然沒有開源源代碼,但是博主正在嘗試復現其中的操作。這篇…

醫學影像PACS信息化數字平臺源碼

PACS系統對醫院影像科意義重大&#xff0c;將業務量巨大的影像檢驗流程依托于信息化技術&#xff0c;對于進行信息化建設的醫院而言&#xff0c;是十分必要的。 PACS系統源碼&#xff0c;集成三維影像后處理功能&#xff0c;包括三維多平面重建、三維容積重建、三維表面重建、三…

包裝類, 泛型---java

目錄 一. 包裝類 1.1 基本數據類型和對應的包裝類 1.2 裝箱和拆箱 二. 泛型 2.1什么是泛型 2.2泛型的引入 2.3 泛型類語法 2.4 泛型類的使用 2.5 裸類型(Raw Type)(了解) 2.6 泛型是如何編譯的 2.7 泛型的上界 2.8 泛型方法 一. 包裝類 在 Java 中&#xff0c;由于基本…

uniapp實戰 —— 豎排多級分類展示

效果預覽 完整范例代碼 頁面 src\pages\category\category.vue <script setup lang"ts"> import { getCategoryTopAPI } from /apis/category import type { CategoryTopItem } from /types/category import { onLoad } from dcloudio/uni-app import { compu…

vue指令

v-text 更新元素的 textContent。如果要更新部分的 textContent&#xff0c;需要使用 {{ Mustache }} 插值。 <span v-text"msg"></span> <!-- 和下面的一樣 --> <span>{{msg}}</span>v-html 更新元素的 innerHTML。注意&#xff1a;內…

基于高通MSM8953平臺android9.0的GPIO驅動開發

2.1、注冊設備&#xff1a; 2.1.1、添加編譯選項&#xff1a; 1&#xff09;、修改kernel/msm-4.9/drivers/leds下Makefile文件&#xff1a; obj-$(CONFIG_LED_GPIO) led_gpio.o 2&#xff09;、修改kernel/msm-4.9/drivers/leds下Kconfig文件&#xff1a; config LED_GPIO…

Java實現歸并排序算法

歸并排序算法 &#xff08;1&#xff09;基本思想&#xff1a;歸并&#xff08;Merge&#xff09;排序法是將兩個&#xff08;或兩個以上&#xff09;有序表合并成一個新的有序表&#xff0c;即把待排序序列分為若干個子序列&#xff0c;每個子序列是有序的。然后再把有序子序…

蛋白質序列FeatureDict轉化為TensorDict

主要轉化語句為 tensor_dict {k: tf.constant(v) for k, v in np_example.items() if k in features_metadata}。 增加了特征名稱的選擇&#xff0c;不同特征維度&#xff0c;特征數的判斷等。 from typing import Dict, Tuple, Sequence, Union, Mapping, Optional #import …

postgresql_conf中常用配置項

在 PostgreSQL 的 postgresql.conf 配置文件中&#xff0c;有許多常用的配置項&#xff0c;這些配置項可以根據特定需求和性能優化進行調整。以下是一些常用的配置項及其作用&#xff1a; 1. shared_buffers 用于設置 PostgreSQL 實例使用的共享內存緩沖區大小。增加此值可以…

游戲被攻擊該怎么辦?游戲盾該如何使用,游戲盾如何防護攻擊

隨著Internet互聯網絡帶寬的增加和多種DDOS黑客工具的不斷發布&#xff0c;DDOS拒絕服務攻擊的實施越來越容易&#xff0c;DDOS攻擊事件正在成上升趨勢。出于商業競爭、打擊報復和網絡敲詐等多種因素&#xff0c;導致很多商業站點、游戲服務器、聊天網絡等網絡服務商長期以來一…

Nacos 配置加密功能也太雞肋了吧,有種更好的方式

大家好&#xff0c;我是風箏&#xff0c;微信搜「古時的風箏」&#xff0c;更多干貨 當項目中用了 Nacos 做配置中心&#xff0c;是不是所有的配置都放到里面呢&#xff0c;大部分時候為了省事和統一&#xff0c;系統所有的配置都直接放在里面了&#xff0c;有時候&#xff0c…