日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

追了多年的开发框架,你还认识指针吗?

發布時間:2023/12/4 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 追了多年的开发框架,你还认识指针吗? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一:背景

1. 講故事

高級語言玩多了,可能很多人對指針或者匯編都淡忘了,本篇就和大家聊一聊指針,雖然C#中是不提倡使用的,但你能說指針在C#中不重要嗎?你要知道FCL內庫中大量的使用指針,如String,Encoding,FileStream等等數不勝數,如例代碼:

private unsafe static bool EqualsHelper(string strA, string strB){fixed (char* ptr = &strA.m_firstChar){fixed (char* ptr3 = &strB.m_firstChar){char* ptr2 = ptr;char* ptr4 = ptr3;while (num >= 12) {...}while (num > 0 && *(int*)ptr2 == *(int*)ptr4) {...}}}}public unsafe Mutex(bool initiallyOwned, string name, out bool createdNew, MutexSecurity mutexSecurity){byte* ptr = stackalloc byte[(int)checked(unchecked((ulong)(uint)securityDescriptorBinaryForm.Length))]}private unsafe int ReadFileNative(SafeFileHandle handle, byte[] bytes, out int hr){fixed (byte* ptr = bytes){num = ((!_isAsync) ? Win32Native.ReadFile(handle, ptr + offset, count, out numBytesRead, IntPtr.Zero) : Win32Native.ReadFile(handle, ptr + offset, count, IntPtr.Zero, overlapped));}}

對,你覺得的美好世界,其實都是別人幫你負重前行,退一步說,指針的理解和不理解,對你研究底層源碼影響是不能忽視的,指針相對比較抽象,考的是你的空間想象能力,可能現存的不少程序員還是不太明白,因為你缺乏所見即所得的工具,希望這一篇能幫你少走些彎路。

二:windbg助你理解

指針雖然比較抽象,但如果用windbg實時查看內存布局,就很容易幫你理解指針的套路,下面先理解下指針的一些簡單概念。

1. &、* 運算符

&取址運算符,用于獲取某一個變量的內存地址,?*運算符,用于獲取指針變量中存儲地址指向的值,很抽象吧,看windbg。

unsafe{int num = 10;int* ptr = #var num2 = *ptr;Console.WriteLine(num2);}0:000> !clrstack -l OS Thread Id: 0x41ec (0)Child SP IP Call Site 0000005b1efff040 00007ffc766208e2 *** WARNING: Unable to verify checksum for ConsoleApp4.exe ConsoleApp4.Program.Main(System.String[]) [C:\dream\Csharp\ConsoleApp1\ConsoleApp4\Program.cs @ 25]LOCALS:0x0000005b1efff084 = 0x000000000000000a0x0000005b1efff078 = 0x0000005b1efff0840x0000005b1efff074 = 0x000000000000000a

仔細觀察?LOCALS?中三組鍵值對。

<1>?int* ptr = &num; => 0x0000005b1efff078 = 0x0000005b1efff084

int* ptr叫做指針變量,既然是變量必須得有自己的棧上地址?0x0000005b1efff078?,而這個地址上的值為?0x0000005b1efff084,這不就是num的棧地址嘛,嘿嘿。

<2>?var num2 = *ptr; => 0x0000005b1efff074 = 0x000000000000000a

*ptr?就是用ptr的value?[0x0000005b1efff084]?獲取這個地址指向的值,所以就是10啦。

如果不明白,我畫一張圖,這可是重中之重哦~

2. **運算符

**?也叫二級指針,指向一級指針變量地址的指針,有點意思,如下程序:ptr2指向的就是?ptr的棧上地址, 一圖勝千言。

unsafe{int num1 = 10;int* ptr = &num1;int** ptr2 = &ptr;var num2 = **ptr2;}0:000> !clrstack -l ConsoleApp4.Program.Main(System.String[]) [C:\dream\Csharp\ConsoleApp1\ConsoleApp4\Program.cs @ 26]LOCALS:0x000000305f5fef24 = 0x000000000000000a0x000000305f5fef18 = 0x000000305f5fef240x000000305f5fef10 = 0x000000305f5fef180x000000305f5fef0c = 0x000000000000000a

3. ++、--運算符

這種算術操作常常用在數組或者字符串等值類型集合,比如下面代碼:

fixed (int* ptr = new int[3] { 1, 2, 3 }) { }fixed (char* ptr2 = "abcd") { }

首先ptr默認指向數組在堆上分配的首地址,也就是1的內存地址,當ptr++后會進入到下一個整形元素2的內存地址,再++后又進入下一個int的內存地址,也就是3,很簡單吧,我舉一個例子:

unsafe{fixed (int* ptr = new int[3] { 1, 2, 3 }){int* cptr = ptr;Console.WriteLine(((long)cptr++).ToString("x16"));Console.WriteLine(((long)cptr++).ToString("x16"));Console.WriteLine(((long)cptr++).ToString("x16"));}}0:000> !clrstack -lLOCALS:0x00000070c15fea50 = 0x000001bcaac82da00x00000070c15fea48 = 0x00000000000000000x00000070c15fea40 = 0x000001bcaac82dac0x00000070c15fea38 = 0x000001bcaac82da8

一圖勝千言哈,Console中的三個內存地址分別存的值是1,2,3哈, 不過這里要注意的是,C#是托管語言,引用類型是分配在托管堆中,所以堆上地址會存在變動的可能性,這是因為GC會定期回收內存,所以vs編譯器需要你用fixed把堆上內存地址固定住來逃過GC的打壓,在本例中就是?0x000001bcaac82da0 - (0x000001bcaac82da8 +4)。

三:用兩個案例幫你理解

古語說的好,一言不中,千言無用,你得拿一些例子活講活用,好吧,準備兩個例子。

1. 使用指針對string中的字符進行替換

我們都知道string中有一個replace方法,用于將指定的字符替換成你想要的字符,可是C#中的string是不可變的,你就是對它吐口痰它都會生成一個新字符串,????????的是用指針就不一樣了,你可以先找到替換字符的內存地址,然后將新字符直接賦到這個內存地址上,對不對,我來寫一段代碼,把abcgef?替換成?abcdef, 也就是將?g?替換為?d。

unsafe{//把 'g' 替換成 'd'string s = "abcgef";char oldchar = 'g';char newchar = 'd';Console.WriteLine($"替換前:{s}");var len = s.Length;fixed (char* ptr = s){//當前指針地址char* cptr = ptr;for (int i = 0; i < len; i++){if (*cptr == oldchar){*cptr = newchar;break;}cptr++;}}Console.WriteLine($"替換后:{s}");}----- output ------替換前:abcgef 替換后:abcdef 執行結束啦!

看輸出結果沒毛病,接下來用windbg去線程棧上找找當前有幾個string對象的引用地址,可以在break處抓一個dump文件。

從圖中?LOCALS?中的10個變量地址來看,后面9個有帶地址的都是靠近string首地址:?0x000001ef1ded2d48,說明并沒有新的string產生。

2. 指針和索引遍歷速度大比拼

平時我們都是通過索引對數組進行遍歷,如果和指針進行碰撞測試,您覺得誰快呢?如果我說索引方式就是指針的封裝,你應該知道答案了吧,下面來一起觀看到底快多少???

為了讓測試結果更加具有觀賞性,我準備遍歷1億個數字, 環境為:netframework4.8, release模式

static void Main(string[] args){var nums = Enumerable.Range(0, 100000000).ToArray();for (int i = 0; i < 10; i++){var watch = Stopwatch.StartNew();Run1(nums);watch.Stop();Console.WriteLine(watch.ElapsedMilliseconds);}Console.WriteLine(" -------------- ");for (int i = 0; i < 10; i++){var watch = Stopwatch.StartNew();Run2(nums);watch.Stop();Console.WriteLine(watch.ElapsedMilliseconds);}Console.WriteLine("執行結束啦!");Console.ReadLine();}//遍歷數組public static void Run1(int[] nums){unsafe{//數組最后一個元素的地址fixed (int* ptr1 = &nums[nums.Length - 1]){//數組第一個元素的地址fixed (int* ptr2 = nums){int* sptr = ptr2;int* eptr = ptr1;while (sptr <= eptr){int num = *sptr;sptr++;}}}}}public static void Run2(int[] nums){for (int i = 0; i < nums.Length; i++){int num = nums[i];}}

有圖有真相哈,直接走指針比走數組下標要快近一倍。

四:總結

希望本篇能給在框架上奔跑的您一個友情提醒,不要把指針忘啦,別人提倡不使用的指針在底層框架可都是大量使用的哦~

總結

以上是生活随笔為你收集整理的追了多年的开发框架,你还认识指针吗?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日韩和的一区二区 | 国产欧美日韩一区 | 免费在线观看视频a | 国产精品一区二区在线看 | 国产精品美女自拍视频 | 亚洲专区在线播放 | 欧美性生活一级 | av污| 91pao| 青草视频在线 | 人妻无码久久一区二区三区免费 | 裸体黄色片 | 一级片麻豆 | 在线播放小视频 | 美女又爽又黄又免费 | 日本三级视频在线 | 国模一区二区三区 | 国产手机av在线 | 久久久免费在线观看 | 欧美三级电影在线观看 | 精品无人区无码乱码毛片国产 | 成人特级片 | 亚洲人人精品 | 成人依依| 男男gay动漫| 亚洲人人精品 | 韩日激情视频 | 男人女人拔萝卜视频 | 69国产| 男女黄色又爽大片 | 伊人av网站| 丰满岳乱妇一区二区 | 91久久精品夜夜躁日日躁欧美 | 国产亚洲一区二区不卡 | 欧美成人精精品一区二区频 | 91精品国产综合久久久久久久 | av乱码| 欧州一区二区 | 97少妇| 欧美日韩精品一区二区在线观看 | 日韩电影一区二区三区 | 亚洲精品免费看 | 和漂亮岳做爰3中文字幕 | 中文字幕av在线 | 国产精品夜色一区二区三区 | 超碰成人在线观看 | 久久疯狂做爰流白浆xx | 夜夜摸夜夜爽 | 国产簧片| 婚后打屁股高h1v1调教 | 亚洲首页 | 极品美女高潮出白浆 | 欧美一区二区三区观看 | 久久av资源 | 欧美日韩一区二区综合 | 777精品久无码人妻蜜桃 | 毛片一区二区三区 | 精品在线一区二区三区 | jizzjizzjizz亚洲女| 日韩中文字幕综合 | 美女被揉胸视频 | 黑巨茎大战欧美白妞 | 成人毛片软件 | 国产精久 | 亚州黄色网址 | 国精产品乱码一区一区三区四区 | 色综合图区 | 亚洲免费av一区 | 五月天综合激情网 | 国产网站无遮挡 | 亚洲一区精品视频 | 色综合色婷婷 | 免费黄色一区二区 | 亚洲第99页| 男人的天堂伊人 | 天天宗合网 | 永久免费视频网站直接看 | 久久久久久国产免费a片 | a级性生活视频 | 性欧美精品男男 | 亚洲在线中文字幕 | 精品一区二区三区久久 | 琪琪色在线观看 | 激情网站免费 | 亚洲精品99久久久久中文字幕 | a级黄色片免费看 | 日韩精品视频在线观看免费 | 国产欧美一区二区三区在线看 | 精品影视一区二区 | 激情视频网站在线观看 | 干综合网 | 亚洲一区二区免费电影 | 影音先锋啪啪资源 | 妞妞av| 天天高潮夜夜爽 | 日日爱669| 亚洲激情短视频 | 日韩有色 | 日韩成人免费在线 |