C/C++位段超詳細(xì)整理大全
什么是位段?
位段的聲明與結(jié)構(gòu)是類似的,但是有兩個(gè)不同:
- 位段的成員必須是 int、unsigned int 或signed int 等整型家族。
- 位段的成員名后邊有一個(gè)冒號(hào)和一個(gè)數(shù)字
這是一個(gè)結(jié)構(gòu)體
struct S { int a; int b; int c; int d; };
這是一個(gè)位段
struct A { int a : 2; int b : 5; int c : 10; int d : 30; };
位段的樣子看起來奇奇怪怪的,那個(gè)冒號(hào)和后面的數(shù)字是什么意思呢?
位段位段,它名字里的“位”就是二進(jìn)制位。
冒號(hào)和后面的數(shù)字其實(shí)是它的成員變量在告訴編譯器:
- 成員a:我只需要2個(gè)比特的空間足以!
- 成員b:請(qǐng)給我分配5個(gè)比特的空間吧!
- 成員c:給我來10個(gè)!
- 成員d:我需要的空間大,給我來40個(gè)比特的空間吧!
每個(gè)成員都得到了自己想要的大小的空間,那么位段A的總大小是多少呢?
我們用sizeof來計(jì)算一下:
#include<stdio.h> struct S { int a; int b; int c; int d; }; struct A { int a : 2; int b : 5; int c : 10; int d : 30; }; int main() { printf("結(jié)構(gòu)體S的大小為: %d字節(jié)\n", sizeof(struct S)); printf("位段A的大小為: %d字節(jié)\n", sizeof(struct A)); return 0; }
學(xué)完上一章之后,我們很輕松的計(jì)算出結(jié)構(gòu)體S的大小4*4=16字節(jié)與結(jié)果一致。
再看位段,把成員們所需要的空間大小加起來2+5+10+30=47比特。
已知1字節(jié)=8比特。換算一下位段A的總大小應(yīng)該是6字節(jié)就夠了,可結(jié)果卻是8字節(jié)。
位段的內(nèi)存分配
位段的成員可以是 int unsigned int signed int 或者是 char (屬于 整形家族 )類型。
位段的空間上是按照需要以4個(gè)字節(jié)( int )或者1個(gè)字節(jié)( char )的方式來開辟的。
位段涉及很多不確定因素,位段是不跨平臺(tái)的,注重 可移植的程序應(yīng)該避免使用位段 。
首先聲明:位段有很多用法是標(biāo)準(zhǔn)未定義的,也就是說不同的機(jī)器上或者不同的編譯器上內(nèi)存如何
分配都有所差異,所以一下內(nèi)容中有關(guān)內(nèi)存分配的插圖并不是嚴(yán)格正確的?。?!
舉個(gè)例子:
這是一個(gè)成員是int類型的位段:
struct A { int a : 2; int b : 5; int c : 10; int d : 30; };
這是一個(gè)成員是char類型的位段:
struct S { char a : 3; char b : 4; char c : 5; char d : 4; };
現(xiàn)在假定義一個(gè)位段的變量并進(jìn)行初始化:
struct S { char a : 3; char b : 4; char c : 5; char d : 4; }; struct S s = { 0 }; s.a = 10; s.b = 12; s.c = 3; s.d = 4;
其在VS2013環(huán)境下是這樣進(jìn)行存儲(chǔ)數(shù)據(jù)的:
說明:數(shù)據(jù)是以二進(jìn)制的方式進(jìn)行存儲(chǔ)的。
再次強(qiáng)調(diào):以上的存儲(chǔ)形式僅僅是vs2013環(huán)境下的,每種不同的編譯器在不同的環(huán)境下都有自己存儲(chǔ)的方式 。
位段的跨平臺(tái)問題
問題一:int 位段被當(dāng)成有符號(hào)數(shù)還是無符號(hào)數(shù)是不確定的。
說明:例如一個(gè)整型存儲(chǔ)的時(shí)候,它的最高位是有符號(hào)位還是無符號(hào)位是有明確的規(guī)定的,而位段標(biāo)準(zhǔn)并沒有規(guī)定。有的平臺(tái)會(huì)當(dāng)作有符號(hào)數(shù)處理,有的反之。
問題二:位段中最大位的數(shù)目不能確定。
說明:16位機(jī)器最大16,32位機(jī)器最大32,寫成27,在16位機(jī)器會(huì)出問題。
問題三:位段中的成員在內(nèi)存中從左向右分配,還是從右向左分配標(biāo)準(zhǔn)尚未定義。
說明:
問題四:當(dāng)一個(gè)結(jié)構(gòu)包含兩個(gè)位段,第二個(gè)位段成員比較大,無法容納于第一個(gè)位段剩余的位時(shí),是舍棄剩余的位還是利用,這是不確定的。
說明:
總結(jié):跟結(jié)構(gòu)相比,位段可以達(dá)到同樣的效果,但是可以很好的節(jié)省空間,但是有跨平臺(tái)的問題存在。
總結(jié)
到此這篇關(guān)于C/C++位段的文章就介紹到這了,更多相關(guān)C/C++位段內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實(shí)例分析講解臨時(shí)對(duì)象與右值引用的用法
對(duì)性能來說,許多的問題都需要和出現(xiàn)頻率及本身執(zhí)行一次的開銷掛鉤,有些問題雖然看似比較開銷較大,但是很少會(huì)執(zhí)行到,那也不會(huì)對(duì)程序有大的影響;同樣一個(gè)很小開銷的函數(shù)執(zhí)行很頻繁,同樣會(huì)對(duì)程序的執(zhí)行效率有很大影響。本章中作者主要根據(jù)臨時(shí)對(duì)象來闡述這樣一個(gè)觀點(diǎn)2022-08-08基于Protobuf C++ serialize到char*的實(shí)現(xiàn)方法分析
本篇文章是對(duì)Protobuf C++ serialize到char*的實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹。需要的朋友參考下2013-05-05C語言中strspn()函數(shù)和strcspn()函數(shù)的對(duì)比使用
這篇文章主要介紹了C語言中strspn()函數(shù)和strcspn()函數(shù)的對(duì)比使用,strspn是計(jì)算屬于字符串的字符數(shù)而strcspn則是判斷不屬于,需要的朋友可以參考下2015-08-08Visual Studio 2019 Professional 激活方法詳解
這篇文章主要介紹了Visual Studio 2019 Professional 激活方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05用標(biāo)準(zhǔn)c++實(shí)現(xiàn)string與各種類型之間的轉(zhuǎn)換
這個(gè)類在頭文件中定義, < sstream>庫定義了三種類:istringstream、ostringstream和stringstream,分別用來進(jìn)行流的輸入、輸出和輸入輸出操作。另外,每個(gè)類都有一個(gè)對(duì)應(yīng)的寬字符集版本2013-09-09C++編寫的WebSocket服務(wù)端客戶端實(shí)現(xiàn)示例代碼
本文主要介紹了C++編寫的WebSocket服務(wù)端客戶端實(shí)現(xiàn)示例代碼,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10C++實(shí)現(xiàn)LeetCode(110.平衡二叉樹)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(110.平衡二叉樹),本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07