高階語言玩多了,可能很多人對指標或者彙編都淡忘了,本篇就和大家聊一聊指標,雖然c#中是不提倡使用的,但你能說指標在c#中不重要嗎?你要知道fcl內庫中大量的使用指標,如string,encoding,filestream
等等數不勝數,如例**:
private unsafe static bool equalshelper(string stra, string strb)
while (num > 0 && *(int*)ptr2 == *(int*)ptr4) }}
}public unsafe mutex(bool initiallyowned, string name, out bool creatednew, mutexsecurity mutexsecurity)
private unsafe int readfilenative(safefilehandle handle, byte bytes, out int hr)
}
對,你覺得的美好世界,其實都是別人幫你負重前行,退一步說,指標的理解和不理解,對你研究底層原始碼影響是不能忽視的,指標相對比較抽象,考的是你的空間想象能力,可能現存的不少程式設計師還是不太明白,因為你缺乏所見即所得的工具,希望這一篇能幫你少走些彎路。
指標雖然比較抽象,但如果用windbg實時檢視記憶體布局,就很容易幫你理解指標的套路,下面先理解下指標的一些簡單概念。
&
取址運算子,用於獲取某乙個變數的記憶體位址,*
運算子,用於獲取指標變數中儲存位址指向的值,很抽象吧,看windbg。
unsafe
0:000> !clrstack -l
os thread id: 0x41ec (0)
child sp ip call site
locals:
0x0000005b1efff084 = 0x000000000000000a
0x0000005b1efff078 = 0x0000005b1efff084
0x0000005b1efff074 = 0x000000000000000a
仔細觀察locals
中三組鍵值對。
<1>int* ptr = # => 0x0000005b1efff078 = 0x0000005b1efff084
int* ptr
叫做指標變數,既然是變數必須得有自己的棧上位址0x0000005b1efff078
,而這個位址上的值為0x0000005b1efff084
,這不就是num的棧位址嘛,嘿嘿。
<2>var num2 = *ptr; => 0x0000005b1efff074 = 0x000000000000000a
*ptr
就是用ptr的value[0x0000005b1efff084]
獲取這個位址指向的值,所以就是10啦。
**
也叫二級指標,指向一級指標變數位址的指標,有點意思,如下程式:ptr2
指向的就是ptr
的棧上位址, 一圖勝千言。
這種算術操作常常用在陣列或者字串等值型別集合,比如下面**:
fixed (int* ptr = new int[3] )
fixed (char* ptr2 = "abcd")
首先ptr
預設指向陣列在堆上分配的首位址,也就是1的記憶體位址,當ptr++
後會進入到下乙個整形元素2的記憶體位址,再++後又進入下乙個int的記憶體位址,也就是3,很簡單吧,我舉乙個例子:
一圖勝千言哈,console中的三個記憶體位址分別存的值是1,2,3
哈, 不過這裡要注意的是,c#是託管語言,引用型別是分配在託管堆中,所以堆上位址會存在變動的可能性,這是因為gc會定期**記憶體,所以vs編譯器需要你用fixed把堆上記憶體位址固定住來逃過gc的打壓,在本例中就是0x000001bcaac82da0 - (0x000001bcaac82da8 +4)
。
古語說的好,一言不中,千言無用,你得拿一些例子活講活用,好吧,準備兩個例子。
我們都知道string中有乙個replace方法,用於將指定的字元替換成你想要的字元,可是c#中的string是不可變的,你就是對它吐口痰它都會生成乙個新字串,??的是用指標就不一樣了,你可以先找到替換字元的記憶體位址,然後將新字元直接賦到這個記憶體位址上,對不對,我來寫一段**,把abcgef
替換成abcdef
, 也就是將g
替換為d
。
unsafe
");var len = s.length;
fixed (char* ptr = s)
cptr++;}}
console.writeline($"替換後:");
}----- output ------
替換前:abcgef
替換後:abcdef
執行結束啦!
看輸出結果沒毛病,接下來用windbg去執行緒棧上找找當前有幾個string物件的引用位址,可以在break處抓乙個dump檔案。
平時我們都是通過索引對陣列進行遍歷,如果和指標進行碰撞測試,您覺得誰快呢?如果我說索引方式就是指標的封裝,你應該知道答案了吧,下面來一起**到底快多少???
為了讓測試結果更加具有觀賞性,我準備遍歷1億個數字, 環境為:netframework4.8, release模式
static void main(string args)
console.writeline(" -------------- ");
for (int i = 0; i < 10; i++)
console.writeline("執行結束啦!");
console.readline();
}//遍歷陣列
有圖有真相哈,直接走指標比走陣列下標要快近一倍。
希望本篇能給在框架上奔跑的您乙個友情提醒,不要把指標忘啦,別人提倡不使用的指標在底層框架可都是大量使用的哦~
追了多年的開發框架,你還認識指標嗎?
高階語言玩多了,可能很多人對指標或者彙編都淡忘了,本篇就和大家聊一聊指標,雖然c 中是不提倡使用的,但你能說指標在c 中不重要嗎?你要知道fcl內庫中大量的使用指標,如string,encoding,filestream等等數不勝數,如例 private unsafe static bool equ...
你的燈還亮著嗎
1,搞清誰 問題的物件 有問題.2,問題的本質是什麼 大多數問題其實就是你期望的東西和你體驗的東西之間的差別.解決辦法是要麼改變期望,要麼改變體驗.3,不要把他們解決問題的方法誤認為是問題的定義 特別是在你使用自己的解決方法時 要搞清楚問題的定義 4,如果你太輕易的解決了他們的問題,他們永遠不會相信...
分手以後,TA的號碼你還留著嗎
分手?好吧,既然別後再也不聯絡,那手機號碼也不必留著。忍著痛,割捨了美麗的記憶,從此以後,期待天涯海角各自安好。引語 時隔多年,如果突然收到那個曾經恨之入骨的人的資訊或者 心情將如何?我想,時間的流逝早已沖淡了回憶中的痛苦和傷感了吧!取而代之的應該是驚喜和親切,畢竟人間沒有不散的宴席,也沒有不滅的仇...