柔性数组和环形队列之间的故事
之前的文章,講解了柔性數組,有很多人留言,提到一些問題。剛好,之前發關于環形隊列的文章有些問題,這次剛好拿出來一起說一下,并用柔性數組實現一個環形隊列。
柔性數組的上一篇文章
環形隊列C語言實現文章
1、環形隊列文章之前的代碼有bug
/*插入數據*/ 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;是有問題的,應該修改成
p_ring_buff->array[p_ring_buff->W%LEN]?=?data;這里的想法是為了保證寫的位置不會超過總長度,如果超過了總長度,就會從第一個位置重新開始寫。
也歡迎大家對文章的內容提出質疑,如果正確還會有hb的哦,昨晚上的這個小帥哥就收到了我的專屬hb。
在討論中一起學習,會收獲更多哦。
2、柔性數組關于arr[]和arr[0]補充內容
柔性數組的兩種書寫方式
struct?starr{int?i;int?arr[0]; };和
struct?starr{int?i;int?arr[]; };上面都是定義柔性數組的方式。需要注意兩個問題
1、 結構體中必須存在至少一個除柔性數組以外的元素。
2、 柔性數組的必須在結構體的最后一個位置。
關于 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標準引入的,叫做incomplete type,不完全類型,引入的原因是發現這樣的寫法非常實用。
arr[0] 是非標準擴展支持,也就是在C99出現之前的C89,就已經存在這種非標準擴展支持了,有些腦瓜子靈光的人,發現了這個機制,就用起來,然后C99才正式給他納入正規軍。
所以我們寫成 arr[0] 也是沒有問題的,編譯器會自動解釋為柔性數組。
在線編譯網站
https://wandbox.org/
用兩張圖說明吧
如果寫成這樣呢?
我們現在接觸到的編譯器寫成arr[] 肯定是沒有問題的,但是那種特別特別古董的編譯器,可能會提示出錯。
但是寫成 arr[0]肯定是沒有問題的,?當然也是不標準的,不過雖然是不標準的,C語言至少是認識這個東西,不會編譯出錯的。
就醬紫~
3、柔性數組的地址和數組地址問題
我們知道,結構體在定義的時候就已經確定了地址位置,柔性數組實際上是不占用原結構體空間的,柔性數組的空間是使用malloc來申請的,既然是這樣,他們的地址空間就不是在一個位置上的。柔性數組也就純粹是掛羊頭賣狗肉了。
測試地址空間
#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$結構體定義的地址和malloc出來的地址不是一個位置,至少他們不是連續的,而且使用malloc出來的內存后,使用完之后,需要使用free釋放內存。
4、使用柔性數組實現環形隊列
/*?實現的最簡單的ringbuff?有更多提升空間,可以留言說明?*/ #include?"stdio.h" #include?"stdlib.h" #include?"time.h"#define?LEN?64 typedef?int?datatype;/*環形隊列結構體*/ typedef?struct?ring_buff{int?W;int?R;int?array[]; }*ring;/*環形隊列初始化*/ 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; }/*判斷環形隊列是否已經滿了*/ int?get_ring_buff_fullstate(struct?ring_buff?*?p_ring_buff) {/*如果寫位置減去讀位置等于隊列長度,就說明這個環形隊列已經滿*/if((p_ring_buff->W?-?p_ring_buff->R)?==?LEN)return?(1);elsereturn?(0); }/*判斷環形隊列為空*/ int?get_ring_buff_emptystate(struct?ring_buff?*?p_ring_buff) {/*如果寫位置和讀的位置相等,就說明這個環形隊列為空*/if(p_ring_buff->W?==?p_ring_buff->R)return?(1);elsereturn?(0); } /*插入數據*/ 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); }/*讀取環形隊列數據*/ 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;/*設置種子*/srand((int)time(0));/*定義一個環形緩沖區*/ring?pt_ring_buff?=?fifo_init();printf("write:\n");/*向環形緩沖區中寫入數據*/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");/*從環形緩沖區中讀出數據*/for(i?=?0;i<10;i++){printf("%d?",ring_buff_get(pt_ring_buff));}printf("\n");/*銷毀一個環形緩沖區*/ring_buff_destory(pt_ring_buff);return?(1); }輸出結果
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$關于環形隊列是否為空的判斷,大家可以思考下,還有沒有更好的判斷方式,歡迎踴躍留言。
推薦閱讀:
專輯|Linux文章匯總
專輯|程序人生
專輯|C語言
我的知識小密圈
總結
以上是生活随笔為你收集整理的柔性数组和环形队列之间的故事的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据库可疑修复的方法
- 下一篇: Unity-TA 成长之路(一)初识渲染