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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

写给过去的自己-No.2-数据结构篇-初尝柔性数组

發(fā)布時間:2025/4/14 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 写给过去的自己-No.2-数据结构篇-初尝柔性数组 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

??? 過去你的自己,你好。
??? 照顧寶寶,寫完第一篇就沒什么時間,既然上次講的就是數(shù)據(jù)結(jié)構(gòu),這次也講點相關(guān)的。
??? 其實接觸柔性數(shù)組也是個比較奇妙的過程,你以后會遇到個學(xué)長,畢業(yè)后從事軟件行業(yè),在中興鍛煉過,將會給你很多軟件方面的啟發(fā)。一次討論結(jié)構(gòu)體內(nèi)數(shù)據(jù)結(jié)構(gòu) 類型強制轉(zhuǎn)換的問題時(劇透一下,是你用的編譯器中的一個bug導(dǎo)致了ARM操作非對齊的地址所以進入hardfault,這個問題和今天講的沒關(guān)系,以 后再開題),聽到了“柔性數(shù)組”這個關(guān)鍵字,當(dāng)時沒聽明白也就沒有去深究。然后某日在論壇看到篇好帖講C語言的一些高級用法,看到了一個疑似“柔性數(shù)組” 的說明,細究之后恍然大悟原來柔性數(shù)組是這么回事。不過另一個問題來了,感覺沒有什么場合會用到,也就沒有深入下去。結(jié)果就在最近,在做模塊化編程時,發(fā) 現(xiàn)了用柔性數(shù)組極佳的環(huán)境。我就是這樣開始正視柔性數(shù)組。開篇講了這么多廢話的目的是要告訴你:1、多向前輩學(xué)習(xí);2、注意前輩不經(jīng)意吐露的“關(guān)鍵 字”;3、有機會一定要深究“關(guān)鍵字”,會有很大收獲;4、對新的知識再深究下應(yīng)用環(huán)境。
??? 數(shù)組一般都是靜態(tài)的,所謂靜態(tài)就是在編譯之時就已經(jīng)確定的。如果是全局數(shù)組,則數(shù)組的大小及存放在內(nèi)存中的位置就確定了(靜態(tài)儲存區(qū));若是局部數(shù)組且編 譯器不支持VLA(可變長度數(shù)組),那該數(shù)組在內(nèi)存的位置就在運行時分配(棧區(qū)域),但是數(shù)組的大小還是在編譯之時就會確定下來(若編譯器支持C99的 VLA,則僅限局部數(shù)組可使用可變長度)。從上面兩種情況可以看出,不管數(shù)組最終存放在哪里,數(shù)組的大小是需要在編譯時確定的(C語言中規(guī)定申請數(shù)組時中 括號內(nèi)的數(shù)據(jù)必須是常量),那問題就來了,如果你想開發(fā)一個軟件模塊且日后不想根據(jù)不同的應(yīng)用修改代碼,那用我們上述方法的數(shù)組肯定是不行的,因為不知道 模塊在被使用時數(shù)組的大小(其實可以簡單的方法解決--宏定義數(shù)組大小,有機會再解釋)。
??? 上述就是問題的提出,下面介紹幾個豆知識:
???? 1、int a = 0;那a就是變量名,其實就是內(nèi)存的一個別名。若a的地址為0x200000FE,則a就是內(nèi)存0x200000FE的別名
???? 2、struct t
????????? {
?????????????? unsigned char wLen;
???????????????unsigned char awData[7];
?????????? };

結(jié)構(gòu)體t的大小為8個字節(jié),如果t申請在內(nèi)存為0x20000000的內(nèi)存上,那t.awData[6]的地址位0x20000007上,t.awData[7]的地址為0x20000008,即結(jié)構(gòu)體t所有成員所占內(nèi)存的后面一個字節(jié)內(nèi)存。

??? 再回到靜態(tài)/動態(tài)數(shù)組上來,目測靜態(tài)數(shù)組不能滿足模塊化編程的需要,那就看看有沒有動態(tài)數(shù)組。既然是動態(tài),那就是在設(shè)備運行時進行操作,而數(shù)組又是一種數(shù) 據(jù)結(jié)構(gòu),也需要分配內(nèi)存,這樣很容易就想到“動態(tài)分配malloc”來解決數(shù)組大小既定的問題。看一下下面的結(jié)構(gòu)體。

1 typedef struct _tTest_ 2 { 3 unsigned char wLen; /* Length of data */ 4 unsigned char awData[0]; /* Data field */ 5 }T_TEST; 6 7 T_TEST t = {0}; /* Create a "t" */

?

??? 依舊是類似的結(jié)構(gòu)體t,不同的是成員數(shù)組awData的大小為0,通過sizeof (T_TEST)可以發(fā)現(xiàn)結(jié)構(gòu)體t的大小為1 byte,說明數(shù)組awData不占內(nèi)存,那這個數(shù)組還有什么意義呢?看一下豆知識1,變量名實際上就是內(nèi)存地址的別名,那么這個長度為0的數(shù)組實際上就 是某個內(nèi)存地址的一個別名。那t.awData[0]是哪個內(nèi)存地址的別名呢?從豆知識2可知它代表的是結(jié)構(gòu)體t后面的一個byte內(nèi)存,依次類 推,awData[9]就是這個結(jié)構(gòu)體t后面第10個byte的內(nèi)存。如果結(jié)構(gòu)體t后面的N個byte內(nèi)存都不被其他變量使用,那t后面的N個byte內(nèi) 存就可視為數(shù)組awData的可用范圍,即awData數(shù)組的長度為N個字節(jié)。也就是說,如果你能控制N的大小,你就能自由地控制數(shù)組awData的大 小,那如何在運行過程中動態(tài)地控制這個N呢?使用malloc。

1 T_TEST *ptTest = NULL; 2 int wLen = 10; /* Get 10-byte length */ 3 4 ptTest = (T_TEST*)malloc(sizeof(T_TEST) + wLen); /* Create the space for array */ 5 6 if(ptTest != NULL) 7 { 8 ptTest->awData[9] = 10; /* Operate the last byte of array */ 9 }

??? 上例中就是通過malloc在內(nèi)存的堆區(qū)域中申請了一塊內(nèi)存區(qū)域,這個區(qū)域由兩部分組成,一個是T_TEST結(jié)構(gòu)體的大小(1 byte),另一個就是數(shù)組的長度wLen。通過這個方法可以確保結(jié)構(gòu)體后面的wLen個內(nèi)存是不會被其他變量占用的,這樣數(shù)組就可以安全地使用。當(dāng)數(shù)組 用完以后,可以free釋放該塊內(nèi)存,再根據(jù)具體要求修改wLen重新申請,這樣這個數(shù)組的長度就變得可變了,這就是柔性數(shù)組,既不用擔(dān)心數(shù)組定義過大而 浪費空間,又不會因為數(shù)組定義過小而發(fā)生越界操作。
??? 再談?wù)剬嶋H的應(yīng)用場景,我開發(fā)的某個軟件模塊中有兩個邏輯運算功能,于是我將可以對這個模塊的數(shù)據(jù)結(jié)構(gòu)做如下定義

1 typedef _LOGIC_ 2 { 3 int wLogicOp; /* Logic operation type: AND/OR/XOR */ 4 int wLogicInputA; /* Logic input value A */ 5 int wLogicInputB; /* Logic input value B */ 6 }T_LOGIC; 7 8 typedef _MODULE_FUNC_ 9 { 10 int wFuncEn; /* Enable or disable logic func */ 11 int wLogicOutput; /* Output operation of logic */ 12 T_LOGIC tLogic1; /* Logic func 1 */ 13 T_LOGIC tLogic2; /* Logic func 2 */ 14 }T_MODULE_FUNC;

結(jié)構(gòu)體T_LOGIC定義了邏輯運算的基本單元,包含了邏輯運算的操作(與或非等)和邏輯輸入,而結(jié)構(gòu)體T_MODULE_FUNC則是軟件模塊所定義的 數(shù)據(jù)結(jié)構(gòu),可以看出軟件模塊定義了兩個邏輯運算基本單元tLogic1和tLogic2,tLogic1的運算結(jié)果將作為tLogic2的輸入繼續(xù)執(zhí)行下 一級邏輯運算。如果說產(chǎn)品的需求就是兩級的邏輯運算,那這個軟件模塊是可以滿足要求,但如果說產(chǎn)品需求是三級邏輯運算,那原有的數(shù)據(jù)結(jié)構(gòu)就不適用,代碼也 要改,則模塊的復(fù)用性就差,所以不能定義個tLogic3來解決該問題。為了解決這個問題,我們可以把原來的結(jié)構(gòu)修改成這樣:

1 typedef _MODULE_FUNC_ 2 { 3 int wFuncEn; /* Enable or disable logic func */ 4 int wLogicOutput; /* Output operation of logic */ 5 T_LOGIC tLogic[NUM_OF_LOGIC]; /* Logic unit */ 6 }T_MODULE_FUNC;

這樣軟件模塊通過宏定義NUM_OF_LOGIC的數(shù)值就可以我需要多少級的邏輯運算,這種方法實現(xiàn)比較簡單,也易于理解,但有時候在整體代碼框架下這個 宏定義的位置需要考慮清楚,同時要關(guān)心頭文件的包含順序。為了讓模塊與其它模塊更少耦合,讓模塊更好用,可以在這里使用柔性數(shù)組:

1 typedef _MODULE_FUNC_ 2 { 3 int wFuncEn; /* Enable or disable logic func */ 4 int wLogicOutput; /* Output operation of logic */ 5 T_LOGIC tLogic[0]; /* Logic unit */ 6 }T_MODULE_FUNC;

這樣就可以不用事先定義這個NUM_OF_LOGIC宏定義,而在運行過程中動態(tài)的申請和使用,是不是很方便呢(其實很多情況下還是宏定義方便,呵呵)。

終于還是寫完了,這篇寫了好長時間,有了寶寶之后屬于自己的時間少且零散,勸你還是在萌萌降臨之前多多學(xué)習(xí),我也盡可能的多總結(jié)點東西給你,希望你能收的到。

寫在最后:借個地方向你感嘆一下生活,你以后某天會放棄一個多年的向往,很多時候你會面臨抉擇,哪一個選項都伴隨著犧牲,你自己要考慮清楚什么更重要。當(dāng) 你遇到這樣的糾結(jié)時,安慰自己,根本就沒有那個選擇,你在做的是你認為最重要的。我不想干預(yù)你太多想法,但記住一點,你有家庭的責(zé)任,請以整個家庭的角度 考慮問題。

轉(zhuǎn)載于:https://www.cnblogs.com/ianhom/p/4517704.html

總結(jié)

以上是生活随笔為你收集整理的写给过去的自己-No.2-数据结构篇-初尝柔性数组的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。