最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

實(shí)例講解C語(yǔ)言編程中的結(jié)構(gòu)體對(duì)齊

 更新時(shí)間:2016年04月20日 11:24:07   作者:阿凡盧  
這篇文章主要介紹了C語(yǔ)言編程中的結(jié)構(gòu)體對(duì)齊,值得注意的是一些結(jié)構(gòu)體對(duì)齊的例子在不同編譯器下結(jié)果可能會(huì)不同,需要的朋友可以參考下

Q:關(guān)于結(jié)構(gòu)體的對(duì)齊,到底遵循什么原則?
A:首先先不討論結(jié)構(gòu)體按多少字節(jié)對(duì)齊,先看看只以1字節(jié)對(duì)齊的情況:

#include <stdio.h>
#include <string.h>

#define PRINT_D(intValue)   printf(#intValue" is %d\n", (intValue));
#define OFFSET(struct,member) ((char *)&((struct *)0)->member - (char *)0)

#pragma pack(1)

typedef struct
{
  char  sex;
  short  score;
  int   age;
}student;

int main()
{
  PRINT_D(sizeof(student))
  PRINT_D(OFFSET(student,sex))
  PRINT_D(OFFSET(student,score))
  PRINT_D(OFFSET(student,age))
  return 0;
}

輸出:

sizeof(student) is 7
OFFSET(student,sex) is 0
OFFSET(student,score) is 1
OFFSET(student,age) is 3

可以看到,如果按1字節(jié)對(duì)齊,那么結(jié)構(gòu)體內(nèi)部的成員緊密排列,sizeof(char) == 1, sizeof(short) == 2, sizeof(int) == 4.

修改上面的代碼, 去掉#pragma pack語(yǔ)句,代碼如下:

#include <stdio.h>
#include <string.h>

#define PRINT_D(intValue)   printf(#intValue" is %d\n", (intValue));
#define OFFSET(struct,member) ((char *)&((struct *)0)->member - (char *)0)

typedef struct
{
  char  sex;
  short  score;
  int   age;
}student;

int main()
{
  PRINT_D(sizeof(student))
  PRINT_D(OFFSET(student,sex))
  PRINT_D(OFFSET(student,score))
  PRINT_D(OFFSET(student,age))
  return 0;
}

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

sizeof(student) is 8
OFFSET(student,sex) is 0
OFFSET(student,score) is 2
OFFSET(student,age) is 4

此時(shí),各個(gè)成員之間就不像之前那樣緊密排列了,而是有一些縫隙。這里需要介紹下對(duì)齊原則:

此原則是在沒(méi)有#pragma pack語(yǔ)句作用時(shí)的原則(不同平臺(tái)可能會(huì)有不同):

原則A:struct或者union的成員,第一個(gè)成員在偏移0的位置,之后的每個(gè)成員的起始位置必須是當(dāng)前成員大小的整數(shù)倍;

原則B:如果結(jié)構(gòu)體A含有結(jié)構(gòu)體成員B,那么B的起始位置必須是B中最大元素大小整數(shù)倍地址;

原則C:結(jié)構(gòu)體的總大小,必須是內(nèi)部最大成員的整數(shù)倍;

依據(jù)上面3個(gè)原則,我們來(lái)具體分析下: sex在偏移0處,占1字節(jié);score是short類型,占2字節(jié),score必須以2的整數(shù)倍為起始位置,所以它的起始位置為2; age為int類型,大小為4字節(jié),它必須以4的整數(shù)倍為起始位置,因?yàn)榍懊嬗衧ex占1字節(jié),填充的1字節(jié)和score占2字節(jié),地址4已經(jīng)是4的整數(shù)倍,所以age的位置為4.最后,總大小為4的倍數(shù),不用繼續(xù)填充。

繼續(xù)修改上面的代碼,增加#pragma pack語(yǔ)句:

#include <stdio.h>
#include <string.h>

#define PRINT_D(intValue)   printf(#intValue" is %d\n", (intValue));
#define OFFSET(struct, member) ((char *)&((struct *)0)->member - (char *)0)

#pragma pack(4)

typedef struct
{
  char  sex;
  short  score;
  int   age;
}student;

int main()
{
  PRINT_D(sizeof(student))
  PRINT_D(OFFSET(student,sex))
  PRINT_D(OFFSET(student,score))
  PRINT_D(OFFSET(student,age))
  return 0;
}

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

sizeof(student) is 8
OFFSET(student,sex) is 0
OFFSET(student,score) is 2
OFFSET(student,age) is 4

具體分析下:

有了#pragma pack(4)語(yǔ)句后,之前說(shuō)的原則A和C就不適用了。實(shí)際對(duì)齊原則是自身對(duì)齊值(成員sizeof大小)和指定對(duì)齊值(#pragma pack指定的對(duì)齊大小)的較小者。依次原則,sex依然偏移為0, 自身對(duì)齊值為1,指定對(duì)齊值為4,所以實(shí)際對(duì)齊為1; score成員自身對(duì)齊值為2,指定對(duì)齊值為4,實(shí)際對(duì)齊為2;所以前面的sex后面將填充一個(gè)1字節(jié),然后是score的位置,它的偏移為2;age自身對(duì)齊值為4,指定對(duì)齊為4,所以實(shí)際對(duì)齊值為4;前面的sex和score正好占用4字節(jié),所以age接著存放;它的偏移為4.

Q:關(guān)于位域的問(wèn)題,空域到底表示什么?
A:它表示之后的位域從新空間開(kāi)始。

#include <stdio.h>
#include <string.h>

#define PRINT_D(intValue)   printf(#intValue" is %d\n", (intValue));
#define OFFSET(struct, member) ((char *)&((struct *)0)->member - (char *)0)

typedef struct 
{
  int a : 1;
  int b : 3;
  int : 0;
  int d : 2;
}bit_info;

int main()
{
  PRINT_D(sizeof(bit_info))
  return 0;
}

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

sizeof(bit_info) is 8

bit_info中的a, b占用4個(gè)字節(jié)的前4位,到int:0; 時(shí)表示此時(shí)將填充余下所有沒(méi)有填充的位,即剛剛的4個(gè)字節(jié)的余下28位;int d:2; 將從第四個(gè)字節(jié)開(kāi)始填充,又會(huì)占用4個(gè)字節(jié),所以總大小為8.

再來(lái)看下面幾個(gè)小例子
例1:

struct A{ 
        char f1 : 3; 
        char f2 : 4; 
        char f3 : 5; 
    };

                    a      b          c
A的內(nèi)存布局:111,1111 *,11111 * * *
位域類型為char,第1個(gè)字節(jié)僅能容納下f1和f2,所以f2被壓縮到第1個(gè)字節(jié)中,而f3只能從下一個(gè)字節(jié)開(kāi)始。因此sizeof(A)的結(jié)果為2。
例2:

struct B{ 
        char f1 : 3; 
        short f2 : 4; 
        char f3 : 5; 
    };

由于相鄰位域類型不同,在VC6中其sizeof為6,在Dev-C++中為2。
例3:

struct C{ 
        char f1 : 3; 
        char f2; 
        char f3 : 5; 
    };

非位域字段穿插在其中,不會(huì)產(chǎn)生壓縮,在VC6和Dev-C++中得到的大小均為3。
考慮一個(gè)問(wèn)題,為什么要設(shè)計(jì)內(nèi)存對(duì)齊的處理方式呢?如果體系結(jié)構(gòu)是不對(duì)齊的,成員將會(huì)一個(gè)挨一個(gè)存儲(chǔ),顯然對(duì)齊更浪費(fèi)了空間。那么為什么要使用對(duì)齊呢?體系結(jié)構(gòu)的對(duì)齊和不對(duì)齊,是在時(shí)間和空間上的一個(gè)權(quán)衡。對(duì)齊節(jié)省了時(shí)間。假設(shè)一個(gè)體系結(jié)構(gòu)的字長(zhǎng)為w,那么它同時(shí)就假設(shè)了在這種體系結(jié)構(gòu)上對(duì)寬度為w的數(shù)據(jù)的處理最頻繁也是最重要的。它的設(shè)計(jì)也是從優(yōu)先提高對(duì)w位數(shù)據(jù)操作的效率來(lái)考慮的。有興趣的可以google一下,人家就可以跟你解釋的,一大堆的道理。
最后順便提一點(diǎn),在設(shè)計(jì)結(jié)構(gòu)體的時(shí)候,一般會(huì)尊照一個(gè)習(xí)慣,就是把占用空間小的類型排在前面,占用空間大的類型排在后面,這樣可以相對(duì)節(jié)約一些對(duì)齊空間。

相關(guān)文章

  • 如何將編譯過(guò)的C++庫(kù)迅速部署在Visual?Studio新項(xiàng)目中

    如何將編譯過(guò)的C++庫(kù)迅速部署在Visual?Studio新項(xiàng)目中

    本文介紹在Visual?Studio中,通過(guò)屬性表,使得一個(gè)新建解決方案中的項(xiàng)目可以快速配置已有解決方案的項(xiàng)目中各類已編譯好的C++第三方庫(kù)的方法,感興趣的朋友跟隨小編一起看看吧
    2024-05-05
  • VC++中HTControl控件類之CHTRichEdit富文本編輯控件實(shí)例

    VC++中HTControl控件類之CHTRichEdit富文本編輯控件實(shí)例

    這篇文章主要介紹了VC++中HTControl控件類之CHTRichEdit富文本編輯控件,是一個(gè)比較實(shí)用的功能,需要的朋友可以參考下
    2014-08-08
  • C++的optional用法實(shí)例詳解

    C++的optional用法實(shí)例詳解

    編程中我們可能會(huì)遇到要處理可能為空的變量,比如說(shuō)容器,基本類型,或者說(shuō)對(duì)象實(shí)例,下面通過(guò)實(shí)例代碼介紹C++的optional用法,感興趣的朋友一起看看吧
    2024-02-02
  • C語(yǔ)言深入講解語(yǔ)句與選擇結(jié)構(gòu)的使用

    C語(yǔ)言深入講解語(yǔ)句與選擇結(jié)構(gòu)的使用

    這篇文章主要為大家介紹了C語(yǔ)言的語(yǔ)句與選擇結(jié)構(gòu),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • 淺談C++11中=delete的巧妙用法

    淺談C++11中=delete的巧妙用法

    本文主要介紹了C++11中=delete的巧妙用法,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • C++的智能指針你真的了解嗎

    C++的智能指針你真的了解嗎

    這篇文章主要為大家詳細(xì)介紹了C++的智能指針,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-03-03
  • C++一個(gè)數(shù)組賦值給另一個(gè)數(shù)組方式

    C++一個(gè)數(shù)組賦值給另一個(gè)數(shù)組方式

    文章介紹了三種在C++中將一個(gè)數(shù)組賦值給另一個(gè)數(shù)組的方法:使用循環(huán)逐個(gè)元素賦值、使用標(biāo)準(zhǔn)庫(kù)函數(shù)std::copy或std::memcpy以及使用標(biāo)準(zhǔn)庫(kù)容器,每種方法都有其適用的場(chǎng)景和注意事項(xiàng)
    2025-02-02
  • C++中的函數(shù)你真的理解了嗎

    C++中的函數(shù)你真的理解了嗎

    這篇文章主要為大家詳細(xì)介紹了C++中的函數(shù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-02-02
  • C語(yǔ)言在屏幕上輸出楊輝三角

    C語(yǔ)言在屏幕上輸出楊輝三角

    這篇文章主要介紹了在屏幕上輸出楊輝三角的方法,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2015-10-10
  • 從零學(xué)習(xí)構(gòu)造系統(tǒng)之bazel示例詳解

    從零學(xué)習(xí)構(gòu)造系統(tǒng)之bazel示例詳解

    這篇文章主要為大家介紹了從零學(xué)習(xí)構(gòu)造系統(tǒng)之bazel示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02

最新評(píng)論

万载县| 阿瓦提县| 新和县| 武鸣县| 靖远县| 吴川市| 马龙县| 寻乌县| 东兴市| 威宁| 钟祥市| 庐江县| 横山县| 卓资县| 辰溪县| 弋阳县| 科技| 望都县| 全椒县| 盐山县| 大城县| 石嘴山市| 汶上县| 山阴县| 万盛区| 新安县| 雅安市| 泰宁县| 亳州市| 哈密市| 读书| 望江县| 湟源县| 六枝特区| 鹤峰县| 济阳县| 博湖县| 北宁市| 昌平区| 宽城| 桂东县|