柔性数组和环形队列之间的故事
之前的文章,講解了柔性數(shù)組,有很多人留言,提到一些問題。剛好,之前發(fā)關(guān)于環(huán)形隊(duì)列的文章有些問題,這次剛好拿出來一起說一下,并用柔性數(shù)組實(shí)現(xiàn)一個(gè)環(huán)形隊(duì)列。
柔性數(shù)組的上一篇文章
環(huán)形隊(duì)列C語言實(shí)現(xiàn)文章
1、環(huán)形隊(duì)列文章之前的代碼有bug
/*插入數(shù)據(jù)*/ int?ring_buff_insert(struct?ring_buff?*?p_ring_buff,int?data) {if(p_ring_buff?==?NULL){printf("p?null\n");return?(-1);?}if(get_ring_buff_fullstate(p_ring_buff)?==?1){printf("buff?is?full\n");return?(-2);}//p_ring_buff->array[p_ring_buff->W%LEN]?=?data;p_ring_buff->array[p_ring_buff->W&(LEN?-1)]?=?data;?p_ring_buff->W?++;//printf("inset:%d?%d\n",data,p_ring_buff->W);return?(0); }這段代碼
p_ring_buff->array[p_ring_buff->W&(LEN?-1)]?=?data;是有問題的,應(yīng)該修改成
p_ring_buff->array[p_ring_buff->W%LEN]?=?data;這里的想法是為了保證寫的位置不會(huì)超過總長(zhǎng)度,如果超過了總長(zhǎng)度,就會(huì)從第一個(gè)位置重新開始寫。
也歡迎大家對(duì)文章的內(nèi)容提出質(zhì)疑,如果正確還會(huì)有hb的哦,昨晚上的這個(gè)小帥哥就收到了我的專屬hb。
在討論中一起學(xué)習(xí),會(huì)收獲更多哦。
2、柔性數(shù)組關(guān)于arr[]和arr[0]補(bǔ)充內(nèi)容
柔性數(shù)組的兩種書寫方式
struct?starr{int?i;int?arr[0]; };和
struct?starr{int?i;int?arr[]; };上面都是定義柔性數(shù)組的方式。需要注意兩個(gè)問題
1、 結(jié)構(gòu)體中必須存在至少一個(gè)除柔性數(shù)組以外的元素。
2、 柔性數(shù)組的必須在結(jié)構(gòu)體的最后一個(gè)位置。
關(guān)于 arr[0] 和 arr[] 的寫法問題,有如下英文解釋
Flexible array members were officially standardized in C99,[4] however compilers accepted zero-sized array members with the same effect (e.g., GCC,[5] Microsoft Visual C[6]).
arr[] 的寫法是C99標(biāo)準(zhǔn)引入的,叫做incomplete type,不完全類型,引入的原因是發(fā)現(xiàn)這樣的寫法非常實(shí)用。
arr[0] 是非標(biāo)準(zhǔn)擴(kuò)展支持,也就是在C99出現(xiàn)之前的C89,就已經(jīng)存在這種非標(biāo)準(zhǔn)擴(kuò)展支持了,有些腦瓜子靈光的人,發(fā)現(xiàn)了這個(gè)機(jī)制,就用起來,然后C99才正式給他納入正規(guī)軍。
所以我們寫成 arr[0] 也是沒有問題的,編譯器會(huì)自動(dòng)解釋為柔性數(shù)組。
在線編譯網(wǎng)站
https://wandbox.org/
用兩張圖說明吧
如果寫成這樣呢?
我們現(xiàn)在接觸到的編譯器寫成arr[] 肯定是沒有問題的,但是那種特別特別古董的編譯器,可能會(huì)提示出錯(cuò)。
但是寫成 arr[0]肯定是沒有問題的,?當(dāng)然也是不標(biāo)準(zhǔn)的,不過雖然是不標(biāo)準(zhǔn)的,C語言至少是認(rèn)識(shí)這個(gè)東西,不會(huì)編譯出錯(cuò)的。
就醬紫~
3、柔性數(shù)組的地址和數(shù)組地址問題
我們知道,結(jié)構(gòu)體在定義的時(shí)候就已經(jīng)確定了地址位置,柔性數(shù)組實(shí)際上是不占用原結(jié)構(gòu)體空間的,柔性數(shù)組的空間是使用malloc來申請(qǐng)的,既然是這樣,他們的地址空間就不是在一個(gè)位置上的。柔性數(shù)組也就純粹是掛羊頭賣狗肉了。
測(cè)試地址空間
#include?"stdio.h" #include"malloc.h"struct?flex_array{int?i;int?arr[0]; };int?main() {int?len?=?10;struct?flex_array?AAA;struct?flex_array?*?p_soft_arr?=?&AAA;p_soft_arr?=?(struct?flex_array?*)malloc(sizeof(struct?flex_array)?+?sizeof(int)*len);printf("%p?%p\n",&AAA,p_soft_arr);printf("sizeof(struct?flex_array)=%ld\n",sizeof(struct?flex_array));return?0; }代碼輸出
weiqifa@bsp-ubuntu1804:~/c$?gcc?ringbuffer.c?&&?./a.out 0x7ffd52554514?0x55e3c0fa1260 sizeof(struct?starr)=4 weiqifa@bsp-ubuntu1804:~/c$結(jié)構(gòu)體定義的地址和malloc出來的地址不是一個(gè)位置,至少他們不是連續(xù)的,而且使用malloc出來的內(nèi)存后,使用完之后,需要使用free釋放內(nèi)存。
4、使用柔性數(shù)組實(shí)現(xiàn)環(huán)形隊(duì)列
/*?實(shí)現(xiàn)的最簡(jiǎn)單的ringbuff?有更多提升空間,可以留言說明?*/ #include?"stdio.h" #include?"stdlib.h" #include?"time.h"#define?LEN?64 typedef?int?datatype;/*環(huán)形隊(duì)列結(jié)構(gòu)體*/ typedef?struct?ring_buff{int?W;int?R;int?array[]; }*ring;/*環(huán)形隊(duì)列初始化*/ struct?ring_buff?*?fifo_init(void) {struct?ring_buff?*?p?=?NULL;p?=?(struct?ring_buff?*)malloc(sizeof(struct?ring_buff)?+?sizeof(datatype)*LEN);if(p?==?NULL){printf("fifo_init?malloc?error\n");return?NULL;}p->W?=?0;p->R?=?0;return?p; }/*判斷環(huán)形隊(duì)列是否已經(jīng)滿了*/ int?get_ring_buff_fullstate(struct?ring_buff?*?p_ring_buff) {/*如果寫位置減去讀位置等于隊(duì)列長(zhǎng)度,就說明這個(gè)環(huán)形隊(duì)列已經(jīng)滿*/if((p_ring_buff->W?-?p_ring_buff->R)?==?LEN)return?(1);elsereturn?(0); }/*判斷環(huán)形隊(duì)列為空*/ int?get_ring_buff_emptystate(struct?ring_buff?*?p_ring_buff) {/*如果寫位置和讀的位置相等,就說明這個(gè)環(huán)形隊(duì)列為空*/if(p_ring_buff->W?==?p_ring_buff->R)return?(1);elsereturn?(0); } /*插入數(shù)據(jù)*/ int?ring_buff_insert(struct?ring_buff?*?p_ring_buff,int?data) {if(p_ring_buff?==?NULL){printf("p_ring_buff?is?null\n");return?(-1);}if(get_ring_buff_fullstate(p_ring_buff)?==?1){printf("buff?is?full\n");return?(-2);}p_ring_buff->array[p_ring_buff->W%LEN]?=?data;p_ring_buff->W?++;//printf("insert:%d?%d\n",data,p_ring_buff->W);return?(0); }/*讀取環(huán)形隊(duì)列數(shù)據(jù)*/ int?ring_buff_get(struct?ring_buff?*?p_ring_buff) {int?data?=?0;if(p_ring_buff?==?NULL){printf("p?null\n");return?(-1);}if(get_ring_buff_emptystate(p_ring_buff)?==?1){printf("buff?is?empty\n");return?(-2);}data?=?p_ring_buff->array[p_ring_buff->R%LEN];p_ring_buff->R++;return?data; }/*銷毀*/ int?ring_buff_destory(struct?ring_buff?*?p_ring_buff) {if(p_ring_buff?==?NULL){printf("p?null\n");return?(-1);}free(p_ring_buff);return?(0); }int?main() {int?i?=?0;int?data;/*設(shè)置種子*/srand((int)time(0));/*定義一個(gè)環(huán)形緩沖區(qū)*/ring?pt_ring_buff?=?fifo_init();printf("write:\n");/*向環(huán)形緩沖區(qū)中寫入數(shù)據(jù)*/for(i?=?0;i<10;i++){data?=?rand()%LEN;ring_buff_insert(pt_ring_buff,data);printf("%d?",data);}printf("\nread:\n");printf("%d?",ring_buff_get(pt_ring_buff));printf("\nread:\n");/*從環(huán)形緩沖區(qū)中讀出數(shù)據(jù)*/for(i?=?0;i<10;i++){printf("%d?",ring_buff_get(pt_ring_buff));}printf("\n");/*銷毀一個(gè)環(huán)形緩沖區(qū)*/ring_buff_destory(pt_ring_buff);return?(1); }輸出結(jié)果
weiqifa@bsp-ubuntu1804:~/c$?gcc?ringbuffer.c?&&?./a.out write: 47?39?31?16?55?25?22?38?41?62 read: 47 read: 39?31?16?55?25?22?38?41?62?buff?is?empty -2 weiqifa@bsp-ubuntu1804:~/c$關(guān)于環(huán)形隊(duì)列是否為空的判斷,大家可以思考下,還有沒有更好的判斷方式,歡迎踴躍留言。
推薦閱讀:
專輯|Linux文章匯總
專輯|程序人生
專輯|C語言
我的知識(shí)小密圈
總結(jié)
以上是生活随笔為你收集整理的柔性数组和环形队列之间的故事的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据库可疑修复的方法
- 下一篇: Unity-TA 成长之路(一)初识渲染