<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > 關于結構體數(shù)據(jù)存儲的對齊問題

          關于結構體數(shù)據(jù)存儲的對齊問題

          作者: 時間:2016-12-01 來源:網(wǎng)絡 收藏
          在C/C 中經(jīng)常需要進行存儲器的操作,關于數(shù)據(jù)如何在存儲器中存儲的問題也是非常重要的,如何在保證數(shù)據(jù)量(信息量)的同時又保證數(shù)據(jù)的存儲量最小,乍一聽感覺沒什么好討論的。但是作為學習嵌入式的必須要明白數(shù)據(jù)的存儲是與數(shù)據(jù)的結構存在密切聯(lián)系的,特別是結構體中的內(nèi)存分配問題。
          首先應該明白基本的類型在內(nèi)存中的大小,char型一般占有1個字節(jié),int型一般占有4個字節(jié),double型一般占有8個字節(jié),short 則占有2個字節(jié)(當然也會存在一定的變化,具體情況依據(jù)編譯器決定)。我們都知道C語言的結構體是一個不同類型數(shù)據(jù)的集合。那么一個結構體到底占多少存儲空間呢?
          首先應該意識到C語言的存儲存在一定的特殊性。在C語言的結構體中需要主要的是數(shù)據(jù)存儲的對齊方式。對齊主要是為了方便數(shù)據(jù)的訪問,提高計算機的處理速度,但是對齊會導致內(nèi)存空間的浪費,這些浪費對于大內(nèi)存空間的設備而言,沒什么必要,但是對于嵌入式系統(tǒng)而言會造成大量的浪費。
          在32bits的系統(tǒng)中對一個寄存器(32bits)的訪問直接訪問,但是對于寄存器中某一個字節(jié)的訪問反而覺得很不方便,因此如果只是單個字節(jié)的訪問反而增加了系統(tǒng)的負擔。對一個寄存器的訪問可以通過一個起始地址來實現(xiàn),但是我們在很多CPU的用戶手冊中都會發(fā)現(xiàn),寄存器的起始地址都能被4整除,這就是為了提高計算速度而采取的一些默認的方式。一個寄存器一般而言占有4個bytes,那么對下一個寄存器的訪問只需要在原來的地址基礎上加上4個 bytes即可。
          對齊的基本作用就是提高系統(tǒng)的功能,特別是訪問存儲器的能力得到提高。
          對齊在使用中有較多的意義。基本的使用原則:
          1、對齊是為了提高系統(tǒng)的訪問速度,一般基本的對齊原則是按著最大的基本類型的長度進行對齊,較小的元素可以幾個組合起來填充一段對齊內(nèi)存,實現(xiàn)基本的對齊,但是需要滿足條件2。
          2、結構體中的元素也要滿足一定的分布條件,就是元素的存儲起始地址要滿足能夠整除該元素類型的長度。
          3、在結構體中存在結構體的情況下,也只是按著結構體中最大的基本類型長度對齊(包含內(nèi)部結構體中的最大基本類型長度)。
          在不同的編譯器之間也存在一定的差別。在linux中最大的對齊長度是 4個字節(jié),也就是如果結構體中的最大的基本類型長度是大于4的,那么也按著4對齊,同時不會按著結構體中最大的基本類型的長度對齊,伴隨著最大基本類型元素的起始地址也不再滿足能夠被最大元素類型長度對齊的原則,而是滿足整除4即可。但如果結構體中最大的基本類型長度小于4,那么按著最大的基本類型長度對齊
          但是在windows中基本上都是按著最大的基本類型長度進行對齊,和一般的原則相似。
          這邊只是我的一些理解其中具體的要具體分析,在實際中建議將最大基本類型的元素放在開始的地方,然后將其他的數(shù)據(jù)按著一定的規(guī)律(能否組合起來滿足對齊條件等)定義結構體,這個規(guī)律要根據(jù)實際情況分析。
          下面通過基本的代碼進行演示:
          1. #include
          2. #include

          3. struct aa{
          4. char a;
          5. double b;
          6. short c;
          7. };

          8. struct bb
          9. {
          10. doublea;
          11. short b;
          12. char c;
          13. };

          14. struct cc
          15. {
          16. struct bb s1;
          17. char s2;
          18. };

          19. struct dd
          20. {
          21. struct aa s1;
          22. char s2;
          23. };

          24. #pragma pack(1)
          25. struct ee
          26. {
          27. double a;
          28. short b;
          29. char c;
          30. };

          31. struct ff
          32. {
          33. char a;
          34. double b;
          35. short c;
          36. };
          37. #pragmapack()

          38. struct gg
          39. {
          40. char a;
          41. };

          42. struct jj
          43. {
          44. char a;
          45. short b;
          46. };

          47. intmain()
          48. {

          49. printf("doublesize is %d %d %d",sizeof(double),sizeof(short),sizeof(char));
          50. printf("size of s1 = %dsize of s2 = %d",sizeof(struct aa),sizeof(struct bb));

          51. printf("size of t1 = %dsize of dd = %d",sizeof(struct cc),sizeof(struct dd));

          52. printf("size of struct ee = %dsize of struct ff = %dsize of struct gg = %dsize of struct jj = %d",
          53. sizeof(struct ee),sizeof(struct ff),sizeof(struct gg),sizeof(struct jj));
          54. exit(0);
          55. }
            上一頁 1 2 下一頁

          評論


          技術專區(qū)

          關閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();