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

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

pvzclass是如何實現(xiàn)的?pvzclass源代碼初步分析(9)Extensions.h & utils.h

2021-08-16 09:02 作者:__W1thoutD0ubt  | 我要投稿

Extensions.h?和?utils.h?都可以實現(xiàn)一些常用的修改功能。

Extensions.h?大部分修改都是功能類的,而?utils.h?的修改都是數(shù)值類的。

不同于之前介紹的頭文件,這兩個頭文件直接定義了函數(shù),而非先聲明,再由其他文件完成定義。

建議在閱讀本篇前先閱讀第4篇的內(nèi)容。

注:本文以2021.8.12更新的版本為準(zhǔn)。

Extensions.h?

Extensions.h?開頭有這樣一段宏定義:

前三個宏比較簡單,是一個帶控制的 WriteMemory() ,適配三種整數(shù)型變量?!?/p>

剩下的五個宏學(xué)過匯編的一眼就能看出來,這是把匯編語言翻譯成機(jī)器碼。

Extensions.h?實現(xiàn)的部分功能僅僅在跳轉(zhuǎn)條件上進(jìn)行調(diào)整,另外定義一個無參數(shù)版本的宏也可以方便修改。

Extensions.h?的大部分功能都是這樣的(有的還需要其他參數(shù)):

以 OverlapPlanting(b)?為例

可以看出,之前 MEMMOD?類宏中的"b"就是函數(shù)的參數(shù)。顯然它就是個開關(guān)。

而圖示函數(shù)在 MEMMOD?類宏中直接使用數(shù)值,從寫入的地址來看,這應(yīng)該是機(jī)器碼。

當(dāng)然,作者顯然沒有把機(jī)器碼直接背下來,而是利用其他軟件,將匯編代碼轉(zhuǎn)化為機(jī)器碼。

對于一段匯編代碼,作者大部分采取轉(zhuǎn)化為機(jī)器碼后拼接的方法。因此,Extensions.h?中會出現(xiàn)這種乍一看很反常的代碼:

看地址,像是修改代碼;看數(shù)值,像是修改常量

其實大部分時候這還是在修改代碼,只是形式上有些偷懶而已。

當(dāng)然,也有使用其他方法實現(xiàn)自身功能的函數(shù)。比如?VasePerspect(b),就是用常規(guī)方法進(jìn)行代碼注入:

雖然形式變了,但基本的實現(xiàn)方式并未變化。

utils.h

和 events 組件一樣,utils.h 也是由 YouTheB(github名)補(bǔ)充到 pvzclass 中的。

實際上這個文件并未包含在 pvzclass.h 中。

utils.h?中所有函數(shù)都包含在命名空間?Utils?中。

utils.h?和大部分頭文件一樣,開頭都是 #pragma once?和包含的頭文件。

然后是變量類型定義和宏定義:

果然,pvzclass?的絕大部分功能都有這倆。

但在文件末尾,兩個宏定義被移除了:

前六個是修改植物基本屬性的函數(shù),原理都很簡單。

在PVZ中,這些基本屬性是用結(jié)構(gòu)體數(shù)組(當(dāng)然也可能是二維數(shù)組)存儲的。

地址變量 address?的第一部分是統(tǒng)一的 0x69F2C??,實際上就是指定了某一屬性(或第一維)。第二部分就是下標(biāo)(或第二維)了。

SetSunValue(sun)?更簡單,單純 Write(x,y)?而已。

readmemory(t)?則是個套皮?Read(t) 。

真·套皮

剩余的三個函數(shù)中,isvalid(s,l,r)?和 t(a)?都是 GetAddress(s,l,r)?的輔助函數(shù)。

不難看出,isvalid(s,l,r)?判斷一個字符串(或其子串)是否滿足中括號匹配

而 t(a)?則是套皮的 isalnum(a) 。

isalnum(a)?可以檢查某一字符是否為數(shù)字或英文字母(包括大小寫),如果是就返回 true ,否則返回 false。

下面分析?GetAddress(s,l,r)。

GetAddress()

在匯編語言中,常用 [address]?表示指針 address?所指向的值。

但這種表示形式不能嵌套,對于多級指針,只能用多個語句實現(xiàn)。

而 GetAddress(s,l,r)?可以直接識別這種表達(dá)式(但不能有減法運(yùn)算)并給出結(jié)果,即使表達(dá)式中有多層嵌套。

我們從頭開始分析:

第一部分

這段代碼的作用很明顯,是在一開始判斷表達(dá)式是否有括號失配的低級錯誤。

時間復(fù)雜度%5Crm%20O(n)。

第二部分

這里 top?只有定義而沒有應(yīng)用,它在下一段代碼才能派上用場。

這一部分中 l?和 r?的作用應(yīng)該很明確了。它們表示的是子串的范圍。

這一部分的作用為:判定 s(或它的一個子串)是否表示?16?進(jìn)制數(shù)值。如果是,就將其轉(zhuǎn)為 10?進(jìn)制并返回。

這一部分的時間復(fù)雜度也是%5Crm%20O(n)。

第三部分

從這部分代碼開始,s?肯定是一個中括號括起的表達(dá)式。

開頭出現(xiàn)了一個名為?v?的 vector<int>。

結(jié)合開頭將 l-1、中間將 r?分別加入 v,以及每當(dāng)有同級?+?就將編號加入 v,可以初步判定,這是在根據(jù) +?將字符串分割為若干子串。

這一段的時間復(fù)雜度為%5Crm%20O(n)。

又因為這個表達(dá)式默認(rèn)只有?+?一種二元運(yùn)算符,這些子串要么是?16?進(jìn)制數(shù),要么是中括號括起的表達(dá)式。

接下來的代碼也不難理解,就是遞歸處理各個子串。

如果是 16?進(jìn)制數(shù),就會在自調(diào)用的第二部分代碼算出數(shù)值,并立刻返回;如果是表達(dá)式,就會繼續(xù)遞歸,直到求得數(shù)值為止。

在運(yùn)算部分的代碼中,need?表示這個子串是否由中括號擴(kuò)起。結(jié)合中括號的作用和代碼內(nèi)容,不難理解該變量的意義。

GetAddress()?前有這樣一句注釋:


這個%5Crm%20O(n)大概率指的是時間復(fù)雜度。

實際上,對于部分字符串,如括號失配的字符串、純16進(jìn)制數(shù)串,時間復(fù)雜度確實是%5Crm%20O(n),原因顯然。

不過對于另一部分字符串,實際上時間復(fù)雜度就有可能大于%5Crm%20O(n)

在第三部分代碼中,每次遞歸都只會去除一層中括號,剩下的子串會在遞歸調(diào)用第三部分的代碼時重復(fù)遍歷,拉低計算效率。

對于形如"[[[[[[[[[[[[......6A9EC0]]]]]]]]]]]]......."(左右中括號數(shù)量相等,6A9EC0可以換為其他 16?進(jìn)制數(shù)),該算法的時間復(fù)雜度甚至?xí)_(dá)到%5Crm%20O(n%5E2),而且還有大量開 vector?導(dǎo)致棧溢出的可能。
不過一般情況下%5Crm%20n不會很大,而且%5Crm%20O(n%5E2)的情況也不容易出現(xiàn),還是可以接受的。

下一篇將分析events,可能是pvzclass(時間上)最多變的部分。

pvzclass是如何實現(xiàn)的?pvzclass源代碼初步分析(9)Extensions.h & utils.h的評論 (共 條)

分享到微博請遵守國家法律
衡东县| 望都县| 元谋县| 勐海县| 弋阳县| 兴城市| 万安县| 伊通| 苏尼特左旗| 永和县| 漳浦县| 孟连| 石楼县| 逊克县| 沾益县| 阿坝| 呼玛县| 广汉市| 雷波县| 通海县| 镇宁| 修武县| 东山县| 嵩明县| 兴仁县| 噶尔县| 广汉市| 馆陶县| 东丽区| 镇原县| 尼木县| 沅江市| 景德镇市| 吴忠市| 古交市| 托里县| 水城县| 安陆市| 丹阳市| 菏泽市| 布尔津县|