免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
深入淺出變長(zhǎng)結(jié)構(gòu)體

深入淺出變長(zhǎng)結(jié)構(gòu)體

1、 問題的引出

        項(xiàng)目中用到數(shù)據(jù)包的處理,但包的大小是不固定的,其長(zhǎng)度由包頭的2字節(jié)決定。比如如下的包頭:88 0f 0a ob cd ef 23 00 。長(zhǎng)度由頭2個(gè)字節(jié)880f決定,考慮字節(jié)序,轉(zhuǎn)為0f88,轉(zhuǎn)為10進(jìn)制3976個(gè)字節(jié)的包長(zhǎng)度。

        這個(gè)時(shí)候存儲(chǔ)包的時(shí)候,一方面可以考慮設(shè)定包的大小固定:如4K=4*1024=4096個(gè)字節(jié),因?yàn)樽畲蟀L(zhǎng)不可能超過4k,但該方法的有缺陷,存在一種極端就是包最小僅含包頭不含數(shù)據(jù)域,此時(shí)包為8個(gè)字節(jié),浪費(fèi)了4096-8 =4088個(gè)字節(jié)的存儲(chǔ)空間。另一方面考慮有沒有一種方法能根據(jù)長(zhǎng)度進(jìn)行存儲(chǔ),或者說初始不分配長(zhǎng)度,計(jì)算出了長(zhǎng)度后再分配存儲(chǔ)呢。而實(shí)際項(xiàng)目中正是通過包頭計(jì)算出了包的整體大小的。

        這就引出了變長(zhǎng)結(jié)構(gòu)體的概念。

 

2、 什么叫變長(zhǎng)結(jié)構(gòu)體?

     如下所示:

  1. struct Var_Len_Struct  
  2. {  
  3.      int nsize;  
  4.      char buffer[0];  
  5. };  


        那結(jié)構(gòu)體是怎么實(shí)現(xiàn)可變長(zhǎng)的呢?如上所示,請(qǐng)注意看結(jié)構(gòu)體中的最后一個(gè)元素,一個(gè)沒有元素的數(shù)組。我們可以通過動(dòng)態(tài)開辟一個(gè)比結(jié)構(gòu)體大的空間,然后讓buffer去指向那些額外的空間,這樣就可以實(shí)現(xiàn)可變長(zhǎng)的結(jié)構(gòu)體了。更為巧妙的是,我們甚至可以nsize存儲(chǔ)字符串buffer的長(zhǎng)度。

       并且,上述的結(jié)構(gòu)體可以擴(kuò)展,比如筆者項(xiàng)目中遇到的存儲(chǔ)數(shù)據(jù)包,前面可能類似包頭的部分(存儲(chǔ)類型、長(zhǎng)度等信息),而后面buffer則存儲(chǔ)數(shù)據(jù)部分。

       同時(shí),需要引起注意的:ISO/IEC 9899-1999里面,這么寫是非法的,這個(gè)僅僅是GNU C的擴(kuò)展,gcc可以允許這一語法現(xiàn)象的存在。但最新的C/C++不知道是否可以,我沒有測(cè)試過。C99允許。

 

3、變長(zhǎng)結(jié)構(gòu)體的好處體現(xiàn)在哪?

        可能有的同學(xué)會(huì)問到,1引出部分如果說定義定長(zhǎng)數(shù)組浪費(fèi)空間,定義一個(gè)指針不也能指向變長(zhǎng)的數(shù)據(jù)域部分嗎?

       是的,是可以實(shí)現(xiàn)的。那么我們就對(duì)比下有什么不同。

       結(jié)構(gòu)體1:s_one,用指針指向數(shù)據(jù)域部分;

       結(jié)構(gòu)體2:s_two, 用[0]的數(shù)組;

       結(jié)構(gòu)體3:s_three, 因?yàn)橛械木幾g器不支持[0],我們用[1]來表示;多了些存儲(chǔ)。

 

  1. #include <stdafx.h>  
  2. #include <iostream>  
  3. using namespace std;  
  4.    
  5. const int BUF_SIZE = 100;  
  6.    
  7. struct s_one  
  8. {  
  9. ints_one_cnt;  
  10. char*s_one_buf;  
  11. };  
  12.    
  13. struct s_two  
  14. {  
  15. ints_two_cnt;  
  16. chars_two_buf[0];  
  17. };  
  18.    
  19. struct s_three  
  20. {  
  21. ints_three_cnt;  
  22. chars_three_buf[1];  
  23. };  
  24.    
  25. int main()  
  26. {  
  27. //賦值用  
  28. constchar* tmp_buf = "abcdefghijklmnopqrstuvwxyz";  
  29. intntmp_buf_size = strlen(tmp_buf);  
  30.    
  31. //<1>注意s_one 與s_two的大小的不同  
  32. cout<< "sizeof(s_one) = " << sizeof(s_one) << endl; //8  
  33. cout<< "sizeof(s_two) = " << sizeof(s_two) << endl; //4  
  34. cout<< "sizeof(s_three) = " << sizeof(s_three) << endl;//5-->8結(jié)構(gòu)體對(duì)齊  
  35. cout<< endl;  
  36.    
  37. //為buf分配100個(gè)字節(jié)大小的空間  
  38. intntotal_stwo_len = sizeof(s_two) + (1 + ntmp_buf_size) * sizeof(char);  
  39. intntotal_sthree_len = sizeof(s_three) + ntmp_buf_size * sizeof(char);  
  40.    
  41. //給s_one buf賦值  
  42. s_one*p_sone = (s_one*)malloc(sizeof(s_one));  
  43. memset(p_sone,0, sizeof(s_one));  
  44. p_sone->s_one_buf= (char*)malloc(1 + ntmp_buf_size);  
  45. memset(p_sone->s_one_buf,0, 1 + ntmp_buf_size);  
  46. memcpy(p_sone->s_one_buf,tmp_buf, ntmp_buf_size);  
  47.    
  48. //給s_two buf賦值  
  49. s_two*p_stwo = (s_two*)malloc(ntotal_stwo_len);  
  50. memset(p_stwo,0, ntotal_stwo_len);  
  51. memcpy((char*)(p_stwo->s_two_buf),tmp_buf, ntmp_buf_size);  //不用加偏移量,直接拷貝!  
  52.    
  53. //給s_three_buf賦值  
  54. s_three*p_sthree = (s_three*)malloc(ntotal_sthree_len);  
  55. memset(p_sthree,0, ntotal_sthree_len);  
  56. memcpy((char*)(p_sthree->s_three_buf),tmp_buf, ntmp_buf_size);  
  57.    
  58. cout<< "p_sone->s_one_buf = " << p_sone->s_one_buf<< endl;  
  59. cout<< "p_stwo->s_two_buf = " << p_stwo->s_two_buf<< endl;  
  60. cout<< "p_sthree->s_three_buf = " <<p_sthree->s_three_buf << endl; //不用加偏移量,直接拷貝!  
  61. cout<< endl;  
  62.    
  63. //<2>注意s_one 與s_two釋放的不同!  
  64. if(NULL != p_sone->s_one_buf)  
  65. {  
  66.         free(p_sone->s_one_buf);  
  67.         p_sone->s_one_buf= NULL;  
  68.    
  69.         if(NULL != p_sone)  
  70.         {  
  71.                free(p_sone);  
  72.                p_sone= NULL;  
  73.         }  
  74.         cout<< "free(p_sone) successed!" << endl;  
  75. }  
  76.    
  77. if(NULL != p_stwo)  
  78. {  
  79.         free(p_stwo);  
  80.         p_stwo= NULL;  
  81.    
  82.         cout<< "free(p_stwo) successed!" << endl;  
  83. }  
  84.    
  85. if(NULL != p_sthree)  
  86. {  
  87.         free(p_sthree);  
  88.         p_sthree= NULL;  
  89.    
  90.         cout<< "free(p_sthree) successed!" << endl;  
  91. }  
  92.    
  93. return0;  
  94. }  


 

       筆者vc6.0的編譯器會(huì)有如下的警告:

 

       運(yùn)行結(jié)果如下:

       對(duì)比結(jié)果,我們能發(fā)現(xiàn):

       <1> 存儲(chǔ)大小方面:s_two的存儲(chǔ)較s_one、s_three都要少,[0]的好處,即用指針的方式需要多開辟存儲(chǔ)空間的。

       <2> 數(shù)據(jù)連續(xù)存儲(chǔ)方面:s_one明顯數(shù)據(jù)域是單獨(dú)開辟的空間,與前的nsize不在連續(xù)的存儲(chǔ)區(qū)域,而s_two,s_three則在連續(xù)的存儲(chǔ)空間下。

       <3>釋放內(nèi)存方面:顯然s_one的指針的方式,需要先釋放數(shù)據(jù)域部分,才能釋放指向結(jié)構(gòu)體的指針變量;而s_two,s_three可以直接釋放。

       總結(jié)如下:

       結(jié)構(gòu)體最后使用0或1的長(zhǎng)度數(shù)組的原因,主要是為了方便的管理內(nèi)存緩沖區(qū),如果你直接使用指針而不使用數(shù)組,那么,你在分配內(nèi)存緩沖區(qū)時(shí),就必須分配結(jié)構(gòu)體一次,然后再分配結(jié)構(gòu)體內(nèi)的指針一次,(而此時(shí)分配的內(nèi)存已經(jīng)與結(jié)構(gòu)體的內(nèi)存不連續(xù)了,所以要分別管理即申請(qǐng)和釋放)。

      而如果使用數(shù)組,那么只需要一次就可以全部分配出來,反過來,釋放時(shí)也是一樣,使用數(shù)組,一次釋放,使用指針,得先釋放結(jié)構(gòu)體內(nèi)的指針,再釋放結(jié)構(gòu)體。還不能顛倒次序。

      其實(shí)變長(zhǎng)結(jié)構(gòu)體就是分配一段連續(xù)的的內(nèi)存,減少內(nèi)存的碎片化,簡(jiǎn)化內(nèi)存的管理

 

4、變長(zhǎng)結(jié)構(gòu)體的應(yīng)用

       <1>Socket通信數(shù)據(jù)包的傳輸;

       <2>解析數(shù)據(jù)包,如筆者遇到的問題。

       <3>其他可以節(jié)省空間,連續(xù)存儲(chǔ)的地方等。

 

 

       未盡事宜,后續(xù)補(bǔ)上……

       2013/9/22pm21:36思于家中床前

 

作者:銘毅天下

轉(zhuǎn)載請(qǐng)標(biāo)明出處,原文地址:http://blog.csdn.net/laoyang360/article/details/11908731

如果感覺本文對(duì)您有幫助,請(qǐng)點(diǎn)擊支持一下,您的支持是我堅(jiān)持寫作最大的動(dòng)力,謝謝!

 

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
WINNT.H內(nèi)的_IMAGE_IMPORT_BY_NAME變長(zhǎng)數(shù)組示例
用UDP實(shí)現(xiàn)可靠文件傳輸
使用openssl中的加密函數(shù)AES、RC4、RSA對(duì)文件加密的一個(gè)例子
UDP socket編程實(shí)例代碼
memset
Http服務(wù)器實(shí)現(xiàn)文件上傳與下載(五)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服