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

C語言帶你學(xué)會位段相關(guān)知識

 更新時間:2023年04月09日 08:51:48   作者:烽起黎明  
這篇文章主要介紹了什么是位段,位段的聲明和結(jié)構(gòu)是類似的,位段的成員必須是 int、unsigned int 或signed int;位段的成員名后邊有一個冒號和一個數(shù)字,本文有詳細(xì)的代碼案例,感興趣的同學(xué)可以參考閱讀

一、什么是位段

位段的聲明和結(jié)構(gòu)是類似的,有兩個不同:

  1. 位段的成員必須是 int、unsigned intsigned int
  2. 位段的成員名后邊有一個冒號和一個數(shù)字
  • 在下面,我分別寫了一個結(jié)構(gòu)體和一個位段,注意看位段的寫法和結(jié)構(gòu)體有什么不同
//結(jié)構(gòu)體
struct A {
	int a;
	int b;
	int c;
	int d;
};
//位段
struct B{
	int _a : 2;
	int _b : 5;
	int _c : 10;
	int _d : 30;
};

然后我們sizeof去計(jì)算一下這個結(jié)構(gòu)體的大小

printf("結(jié)構(gòu)體大?。?d\n", sizeof(struct A));
printf("位段大?。?d\n", sizeof(struct B));

可以看到,結(jié)構(gòu)體的大小是16,位段是8,二者為何會存在區(qū)別呢?原因在于這個: 2嗎?

  • 那根據(jù)位段后面的這些數(shù)字,我們可以初步去斷定可能大小是這些數(shù)組的總和,再轉(zhuǎn)換為字節(jié)的。計(jì)算一下可以知道為47b,在內(nèi)存中1B = 8b,要存下這個47個比特位的話應(yīng)該6個字節(jié)就夠了,但是結(jié)果為什么是8呢?我們不得而知??

在這里插入圖片描述

學(xué)習(xí)了位段的相關(guān)知識后你就知道了

二、位段的內(nèi)存分配

首先來科普一下位段的相關(guān)知識??

  1. 位段的成員可以是 int unsigned int signed int 或者是 char (屬于整形家族)類型
  2. 位段的空間上是按照需要以4個字節(jié)[int]或者1個字節(jié) [char] 的方式來開辟的。
  3. 位段涉及很多不確定因素,位段是不跨平臺的,注重可移植的程序應(yīng)該避免使用位段

那從上面我們就可以提取出一些信息,知道了對于整型而言會開辟出4個字節(jié)的數(shù)據(jù)給到位段作為存放,那接下去呢我們就來分析一下這個位段

  • 仔細(xì)觀察可以得知每個成員都是整型,那首先開辟出32個比特位
    • _a占了2個比特位,還剩下【30b】
    • _b占了5個比特位,還剩下【25b】
    • _c占了10個比特位,還剩下【15b】
    • _d占了30個比特位,但是剩下的【15b】不夠用了,此時編譯器會繼續(xù)開辟出4B,也就是32b的空間來存放

所以最后的結(jié)果就是4 + 4 = 8B

struct B{
		//4Byte - 32bit
	int _a : 2;		//30
	int _b : 5;		//25
	int _c : 10;	//15
		//4Byte - 32bit
	int _d : 30;
	//4 + 4 = 8
};

看了我上面的這樣計(jì)算,你一定會有這些疑問

?? 第一次是32b用剩后的【15b】去哪兒了呢?

?? _d使用的是【15b】+ 后面開辟出來的32b,還是只用到后面的32b呢?

?? 難道所有平臺都是這樣嗎?有沒有不一樣的計(jì)算方法?

上面是很多同學(xué)在課后提出來的疑問,關(guān)于這些,你在看完了我下面的分析后就會明白了?? 內(nèi)存圖分析位段分布

接下去我就通過對位段進(jìn)行分析,然后觀察內(nèi)存分布來揭曉上面究竟是如何計(jì)算的。

為了方便期間,這里換一組位段,但是換湯不換藥

struct S
{
	char a : 3;
	char b : 4;
	char c : 5;
	char d : 4;
};

int main(void)
{
	struct S s = { 0 };
	s.a = 10;
	s.b = 12;
	s.c = 3;
	s.d = 4;
	return 0;
}
  • 首先來看一下存放這個位段需要的字節(jié)數(shù)??梢钥吹竭@個位段中的每個成員都是char類型的,所以編譯器會首先為其分配一個字節(jié)的空間,然后隨著變量的存入,最終是需要三個字節(jié)

在這里插入圖片描述

然后我們來逐一分析一下??

  • 剛才說了,這個位段在內(nèi)存中需要開辟三個字節(jié),這些變量要怎么存呢,首先看到變量a占了3個比特位,那是從左邊的三位開始放還是右邊的三位呢?總不可以從中間開始放吧!

那我們假設(shè)一下,從右邊往左邊放,那么a放完后就是b,占4個比特位,但是放c的時候就放不下了,所以需要在開辟1個字節(jié)的空間,此時d再來放的話也放不下了,所以也要再開辟1個字節(jié) ,最后也就需要3個字節(jié)的空間

在這里插入圖片描述

詳細(xì)分析如下】:

接下去我們就根據(jù)main函數(shù)中對位段各變量的初始化,來看看位段在內(nèi)存中的分布情況:a的初始值為10,不過這是十進(jìn)制,轉(zhuǎn)換為二進(jìn)制形式的話就是[1010],轉(zhuǎn)看位段這里a變量的是占了3位,所以會截?cái)喑?code>010,將它放到第一個字節(jié)處的右邊3個比特位處

  • 接下去是b,初始值為12,轉(zhuǎn)換為二進(jìn)制形式的話就是[1100],而b在內(nèi)存中也剛好是占4個比特位的大小,剛好第一個字節(jié)處還可以放得過,所以繼續(xù)順位放置
  • 然后是c,初始值為3,轉(zhuǎn)換為二進(jìn)制形式的話就是11,但是c在內(nèi)存中也占5個比特位的大小,所以要在前面做一個擴(kuò)充便為[00011],但是第一個字節(jié)放不下了,上面放了【3】+【4】=【7】,只剩下1個比特位,那我們考慮再開一個字節(jié)的空間,為了保持連續(xù)性就直接把這個5個比特位的數(shù)據(jù)放到第二個字節(jié)的右邊
  • 最后的是d,初始值為4,轉(zhuǎn)換為二進(jìn)制形式的話就是100,不過d在內(nèi)存中也占4個比特位的大小,所以要在前面補(bǔ)上一個0,即為[0100],但是第二個字節(jié)也放不過了,只剩三個比特位了,所以我們考慮再開一個字節(jié)的空間,然后放這個d

上面只是我假設(shè)的編譯器執(zhí)行思維,不過真正是怎樣的,我們還是要求證一下

  • 那要怎么求證呢?這個很簡單,既然這些變量都是存放在位段中,那我們剛才都算出所存放的二進(jìn)制形式了。對于內(nèi)存中的地址一般我們看到都是十六進(jìn)制,所以可以考慮把這些二進(jìn)制4個為一組轉(zhuǎn)換為十六進(jìn)制看看
    • 01100010即為——>0x62
    • 00000011即為——>0x03
    • 00000100即為——>0x04
  • 而在內(nèi)存中左邊是低地址,右邊是高地址,所以我們看到的應(yīng)該是62 03 04 cc。來通過【內(nèi)存】觀察一下吧

可以看到,確實(shí)和我們分析得是一模一樣?

在這里插入圖片描述

看完了上面這個,相信你對一開始的那個位段如何去進(jìn)行求解的整個流程應(yīng)該是非常清楚了,留給讀者自己的分析觀察??

三、位段的跨平臺問題

接下去我們再來講講有關(guān)位段的跨平臺的問題

  • int 位段被當(dāng)成有符號數(shù)還是無符號數(shù)是不確定的
  • 位段中最大位的數(shù)目不能確定。(16位機(jī)器最大16,32位機(jī)器最大32)
    • 假設(shè)我們將位段中一個變量所占大小設(shè)置為30,即占30個比特位,那么它在32為機(jī)器上是沒問題的,但是放到早期的16位機(jī)器上去的話,可能連編譯都編不過,因?yàn)楦敬娣挪幌?/li>
  • 位段中的成員在內(nèi)存中從左向右分配,還是從右向左分配標(biāo)準(zhǔn)尚未定義
    • 剛才我分析的時候假設(shè)的是從右往左進(jìn)行分配,但是呢這在其他平臺上可能又是不一樣的了
  • 當(dāng)一個結(jié)構(gòu)包含兩個位段,第二個位段成員比較大,無法容納于第一個位段剩余的位時,是舍棄剩余的位還是利用,這是不確定的
    • 這也就是我們一開始糾結(jié)的【15】到底還用不用的問題,這里給出解答,還是不確定,取決于平臺

總結(jié):跟結(jié)構(gòu)相比,位段可以達(dá)到同樣的效果,但是可以很好的節(jié)省空間,但是有跨平臺的問題存在

  • 這可能還有的老鐵不太理解,舉個例子:假設(shè)結(jié)構(gòu)體A中的這個變量a只可能有【0】【1】【2】【3】這四種取值,那么只需要2個比特位就可以表達(dá)這四個數(shù)字了,即【00】【01】【10】【11】,那我們便可以使用位段來是實(shí)現(xiàn):2,但若是放在普通結(jié)構(gòu)體中的話就只能是一個整型4個字節(jié)32個比特位的大小,這也就浪費(fèi)了很多的空間
  • 同理,若是變量b也只有5種表示形式的話,5個比特位就夠了,c、d也是一樣。那么這個時候位段就派上用場了,若是使用結(jié)構(gòu)體的話就會浪費(fèi)掉很多的空間。所以我們前面在看的時候,結(jié)構(gòu)體所占的空間大小是16B,而位段只有8B

在這里插入圖片描述

四、位段的應(yīng)用

清楚了位段的相關(guān)知識和使用后,可能還是有同學(xué)比較迷惑這個位段到底是用來干嘛的,有什么實(shí)際應(yīng)用場景嗎?我們來看看

  • 比方說這里有個IP數(shù)據(jù)包,有學(xué)習(xí)過《計(jì)算機(jī)網(wǎng)絡(luò)》相關(guān)知識的讀者應(yīng)該都很清楚【不了解可以看看網(wǎng)絡(luò)層知識點(diǎn)匯總】,我們平常在網(wǎng)絡(luò)上和別人互相聊天的時候,所發(fā)送的消息并不是直接在網(wǎng)絡(luò)鏈路上進(jìn)行傳送的,而是會將其封裝到一個數(shù)據(jù)包中,它叫做IP數(shù)據(jù)包,例如我們所發(fā)送的呵呵只是里面的一個數(shù)據(jù)部分,還存在其他很多的字段,這些字段都占有各自的字節(jié)數(shù)
  • 其實(shí)對于這些字節(jié)數(shù)來說,就是使用【位段】來實(shí)現(xiàn),精準(zhǔn)地控制好每個字段需要多少字節(jié)數(shù),,就不會造成浪費(fèi)的現(xiàn)象了

在這里插入圖片描述

五、總結(jié)與提煉

最后來總結(jié)一下本文所學(xué)習(xí)的內(nèi)容??

  • 在本文中,我們首先講到了位段的相關(guān)概念,知道了原來使用結(jié)構(gòu)體還可以實(shí)現(xiàn)位段,不過在看了二者的大小后,卻產(chǎn)生了疑惑,為什么位段所占的大小是這些呢?
  • 在清楚了位段在內(nèi)容中的相關(guān)分布后,我?guī)еx者一步步分析了位段中的成員數(shù)據(jù)到底是怎么一個個存放到內(nèi)存中的,也通過VS中的【內(nèi)存】驗(yàn)證觀察了我們的分析結(jié)果,是正確的
  • 然后便說道了位段這個東西其實(shí)具備很大的不確定性,因?yàn)樗嬖诳缙脚_的問題,在不同平臺下實(shí)現(xiàn)的機(jī)制可能不同,所以就會導(dǎo)致最后的位段大小會不一致
  • 最后,也說道了位段的作用以及其實(shí)際的應(yīng)用場景,讓讀者學(xué)以致用

到此這篇關(guān)于C語言帶你學(xué)會位段相關(guān)知識的文章就介紹到這了,更多相關(guān)C語言位段知識內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++圖書管理系統(tǒng)程序源代碼

    C++圖書管理系統(tǒng)程序源代碼

    這篇文章主要為大家詳細(xì)介紹了C++圖書管理系統(tǒng)程序源代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • C++深入講解哈夫曼樹

    C++深入講解哈夫曼樹

    給定N個權(quán)值作為N個葉子結(jié)點(diǎn),構(gòu)造一棵二叉樹,若該樹的帶權(quán)路徑長度達(dá)到最小,稱這樣的二叉樹為最優(yōu)二叉樹,也稱為哈夫曼樹(Huffman Tree)。哈夫曼樹是帶權(quán)路徑長度最短的樹,權(quán)值較大的結(jié)點(diǎn)離根較近
    2022-05-05
  • C語言實(shí)現(xiàn)簡單的貪吃蛇小游戲

    C語言實(shí)現(xiàn)簡單的貪吃蛇小游戲

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)簡單的貪吃蛇小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • c語言通過opencv實(shí)現(xiàn)輪廓處理與切割

    c語言通過opencv實(shí)現(xiàn)輪廓處理與切割

    這篇文章主要介紹了c語言通過opencv實(shí)現(xiàn)輪廓處理與切割,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01
  • C語言動態(tài)內(nèi)存的分配實(shí)例詳解

    C語言動態(tài)內(nèi)存的分配實(shí)例詳解

    動態(tài)內(nèi)存管理同時還具有一個優(yōu)點(diǎn),當(dāng)程序在具有更多內(nèi)存的系統(tǒng)上需要處理更多數(shù)據(jù)時,不需要重寫程序,下面這篇文章主要給大家介紹了關(guān)于C語言動態(tài)內(nèi)存分配的相關(guān)資料,需要的朋友可以參考下
    2022-06-06
  • 老生常談C/C++內(nèi)存管理

    老生常談C/C++內(nèi)存管理

    下面小編就為大家?guī)硪黄仙U凜/C++內(nèi)存管理。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • 聊聊Qt+OpenCV聯(lián)合開發(fā)之圖像的創(chuàng)建與賦值問題

    聊聊Qt+OpenCV聯(lián)合開發(fā)之圖像的創(chuàng)建與賦值問題

    這篇文章主要介紹了Qt+OpenCV聯(lián)合開發(fā)之圖像的創(chuàng)建與賦值問題,給大家介紹了圖像的克隆及拷貝問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-01-01
  • vscode編譯運(yùn)行c語言報(bào)錯亂碼的解決

    vscode編譯運(yùn)行c語言報(bào)錯亂碼的解決

    本文主要介紹了vscode編譯運(yùn)行c語言報(bào)錯亂碼,文中通過圖文介紹的的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-07-07
  • C語言實(shí)現(xiàn)簡單電子通訊錄(2)

    C語言實(shí)現(xiàn)簡單電子通訊錄(2)

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)簡單電子通訊錄的第二部分,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-06-06
  • VC MFC非模態(tài)對話框的實(shí)現(xiàn)方法

    VC MFC非模態(tài)對話框的實(shí)現(xiàn)方法

    這篇文章主要介紹了VC MFC非模態(tài)對話框的實(shí)現(xiàn)方法,有助于讀者加深對于模態(tài)對話框與非模態(tài)對話框的理解與運(yùn)用,需要的朋友可以參考下
    2014-07-07

最新評論

新绛县| 阿瓦提县| 精河县| 陕西省| 文水县| 云安县| 永新县| 定襄县| 南皮县| 合江县| 安庆市| 山东| 罗定市| 灵台县| 唐河县| 肃宁县| 木兰县| 从江县| 满城县| 潢川县| 日土县| 盘山县| 高州市| 霍城县| 合阳县| 武川县| 舟曲县| 翼城县| 东乌| 垣曲县| 青龙| 织金县| 大埔区| 红桥区| 常熟市| 万年县| 大新县| 腾冲县| 贵南县| 太康县| 彭阳县|