最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

第 26 講:指針(三):指針和數(shù)組

2021-04-10 09:21 作者:SunnieShine  | 我要投稿

前文我們說過了堆內(nèi)存和棧內(nèi)存的基本存儲姿勢,現(xiàn)在我們說一下對于指針相關(guān)的數(shù)組操作。

Part 1 棧內(nèi)存數(shù)組

什么?數(shù)組元素少?是的,那么我們是可以允許使用別的語法來完成這一點的。我們使用關(guān)鍵字 stackalloc 來創(chuàng)建棧內(nèi)存的數(shù)組。

比如這個例子里,我們使用 stackalloc int[10] 來創(chuàng)建一個長度 10 的棧內(nèi)存數(shù)組。稍微注意兩個地方。第一個地方是,stackalloc 替換為 new 的時候,和原始的創(chuàng)建數(shù)組的寫法是一樣的;第二個地方是,左側(cè)變量 arr 的類型是 int* 而不是 int[]。這一點可能你需要注意了。因為棧內(nèi)存分配的結(jié)果必然是一個指針表達的數(shù)組,因此必須用指針表示。

另外,在 C 語言里我們知道,數(shù)組和指針基本上沒有啥大的區(qū)別,因此索引器 [] 可以用在指針上。比如 a[1]p[1] 都是可以的語法。

這樣寫是可以的。不過,C# 里,stackallocnew 有一點不一樣的是,stackalloc 反饋的是一個指針,因此我們不能使用初始化的語法,即那個大括號,寫初始數(shù)值的列表,你必須寫成這樣:

比如這樣。

Part 2 指針的加減運算

數(shù)組是長條形的存儲結(jié)構(gòu),那么我們怎么通過指針來取元素呢?在講數(shù)組的指針操作之前,我們先來說一下指針的加減法。

我們定義的指針變量:

注意 ptr 的初始化語句。我們使用 arr + 1 表示的是取 arr[1] 元素的地址。C# 里,我們定義兩種運算:

  • arr + n 表示取 arr[n] 的地址,即等價于 &arr[n];

  • arr - n 表示取 arr[-n] 的地址,即等價于 &arr[-n]。

可能減法不是很好理解。你將這里 arr 當(dāng)成一個指針,加 n 就表示往后移動,那么減去 n 就是往前移動了。舉個例子。

我們試著看一下這兩個例子。ptr[-1] 表示以 arr[3] 為基準(zhǔn)往前移動 1 個單位,因此此時指向的位置是 arr[2],因此第一個輸出語句是輸出 arr[2] 的數(shù)值 100;而第二個的話,它和 arr[-2] 是一個意思,即指向 arr - 2 這個地方,然后取這個地方的數(shù)值。顯然是 10,因此輸出的就是 10。

正是因為如此,我們需要為指針定義指向變量的類型。因為指針是可以執(zhí)行加減法運算的。如果類型是 void* 的話,由于類型無法確定,因此程序并不知道我們到底需要往前或往后偏移單位的時候,走多遠(yuǎn)的距離。不同的數(shù)據(jù)類型占據(jù)的內(nèi)存空間大小是不一樣的,這就導(dǎo)致了使用 void* 接收會無法確保移動長度的問題。

Part 3 固定語句

在使用棧內(nèi)存數(shù)組的過程中,因為它是在棧內(nèi)存里,因此變量是不會受到 GC 的影響的;但相反,由于數(shù)組被放在堆內(nèi)存里,因此如果我們使用指針取得變量的地址的話,因為是間接取值的關(guān)系,GC 萬一回收了這個數(shù)組的內(nèi)存,這個指針不就產(chǎn)生很嚴(yán)重的內(nèi)存問題了嗎?

因此,C# 發(fā)明了一種機制,叫做數(shù)組的固定(Fix)。固定數(shù)組后,數(shù)組在使用指針運算期間就無法被 GC 回收。

3-1 數(shù)組的固定

固定語句是這么寫的:

我們使用關(guān)鍵字 fixed 來表示,下面的 arr 我需要固定;而等號左側(cè)的變量 parr 這個堆內(nèi)存數(shù)組的首地址。然后,使用大括號就可以在大括號內(nèi)部使用這個 p。但是,我們無法修改 p,只能通過賦值給別的指針變量來修改。比如說 int* q = p; q++; 類似這樣的形式來修改 q 的數(shù)值,p 只能讀取用。

舉個例子,我們要計算一個數(shù)組每一個元素加起來的和。

比如像是這樣的形式。在循環(huán)里,我們使用 ptr 來作為游標(biāo),移動 ptr 的指向來達到遍歷整個數(shù)組的過程。稍微注意一點的地方是,數(shù)組即使固定了,我們也無法通過指針本身來確定數(shù)組的大小。因此,我們還需要一個叫 times 的臨時變量來表示到底移動了多少次。

稍微注意一點的是,它和 C 語言不同,對數(shù)組本身使用地址符號和對數(shù)組的元素使用地址符號都是 C 語言允許的寫法,但是 C# 里,我們只能寫 int* p = arrint* p = &arr[0] 這種格式,而不能寫成 int* p = &arr。

3-2 字符串的固定

和普通數(shù)組稍顯不同的地方是,字符串的固定。字符串的固定被 C# 特殊處理過,因此我們?nèi)绻潭艘粋€字符串的話,那么這個字符串必然是“一個字符數(shù)組,外帶一個終止字符”。

終止字符(Terminator),專門標(biāo)記一個字符串是否結(jié)尾。它寫成 '\0',但我們一般書寫字符串字面量的時候,都不寫它。另外,C# 有特殊處理,即使字符串的中間有這個終止字符都是可以的,它只是在固定字符串的時候才會發(fā)生作用,表示字符串的結(jié)尾。

字符串的固定和數(shù)組的固定寫法完全一樣。

比如這樣。我們直接將字符串的字面量(或者變量)寫到 fixed 語句的小括號里,等號左側(cè)則使用 char* 類型的指針變量來接收。然后,下面使用 for 循環(huán)來遍歷整個字符串。另外,這里我們可以直接以 *ptr != '\0' 作為條件判斷。如果遇到 '\0' 的時候,我們就可以認(rèn)為整個字符串結(jié)束了;否則 ptr 不斷往后移動。

稍微注意一下。字符串在 C# 里是不可變的。換句話說,我們無法通過前文介紹字符串的那些內(nèi)容來改變字符串里的字符;相反地,我們怎么調(diào)用那些方法,最終都是產(chǎn)生一個新的字符串,來作為結(jié)果。但是,我們使用指針的話,字符串不可變的特征就會被打破。

我們來看這一則完整的例子。在最后調(diào)用后,整個字符串的所有字符全都會被改成 'a'。


第 26 講:指針(三):指針和數(shù)組的評論 (共 條)

分享到微博請遵守國家法律
长武县| 金堂县| 高尔夫| 青铜峡市| 鱼台县| 长宁县| 交口县| 通许县| 盐山县| 安丘市| 台江县| 肃北| 无锡市| 衡山县| 班玛县| 崇礼县| 故城县| 琼中| 临洮县| 黄大仙区| 镇原县| 平昌县| 新巴尔虎左旗| 祁阳县| 江阴市| 大理市| 韶关市| 开化县| 揭阳市| 永康市| 南乐县| 寿光市| 汉源县| 吉水县| 阳新县| 辽源市| 绥阳县| 通州市| 遂昌县| 铁力市| 太仆寺旗|