寫出乙個struct,然後sizeof,你會不會經常對結果感到奇怪?sizeof的結果往往都比你宣告的變數總長度要大,這是怎麼回事呢?講講位元組對齊吧.
/******************************分割線
如果體系結構是不對齊的,a中的成員將會乙個挨乙個儲存,從而sizeof(a)為11。顯然對齊更浪費了空間。那麼為什麼要使用對齊呢?
體 繫結構的對齊和不對齊,是在時間和空間上的乙個權衡。對齊節省了時間。假設乙個體繫結構的字長為w,那麼它同時就假設了在這種體系結構上對寬度為w的資料 的處理最頻繁也是最重要的。它的設計也是從優先提高對w位資料操作的效率來考慮的。比如說讀寫時.............此處省略50萬字
上面是你隨便 google一下,人家就可以跟你解釋的,一大堆的道理,我們沒怎麼多時間,討論為何要對齊.直入主題,怎麼判斷記憶體對齊規則,sizeof的結果怎麼來的,請牢記以下3條原則:(在沒有#pragma pack巨集的情況下)
1:資料成員對齊規則:結構(struct)(或聯合(union))的資料成員,第乙個資料成員放在offset為0的地方,以後每個資料成員儲存的起始位置要從該成員大小的整數倍開始(比如int在32位機為4位元組,則要從4的整數倍位址開始儲存。
2:結構體作為成員:如果乙個結構裡有某些結構體成員,則結構體成員要從其內部最大元素大小的整數倍位址開始儲存.(struct a裡存有struct b,b裡有char,int ,double等元素,那b應該從8的整數倍開始儲存.)
3:收尾工作:結構體的總大小,也就是sizeof的結果,.必須是其內部最大成員的整數倍.不足的要補齊.
等你看完此3條原則,2分鐘已經過去,抓緊時間,實戰3分鐘:
typedef struct bb
bb;typedef struct aa
aa;int main()
; #pragma pack(pop)// 恢復對齊狀態
以上結構的大小為16 ,下面分析其儲存情況,首先為m1 分配空間,其偏移量為0 ,滿足我們自己設定的對齊方式(4 位元組對齊),m1 占用1 個位元組。接著開始為m4 分配空間,這時其偏移量為1 ,需要補足3 個位元組,這樣使偏移量滿足為n=4 的倍數(因為sizeof(double) 大於n ),m4 占用8 個位元組。接著為m3 分配空間,這時其偏移量為12 ,滿足為4 的倍數,m3 占用4 個位元組。這時已經為所有成員變數分配了空間,共分配了16 個位元組,滿足為n 的倍數。如果把上面的#pragma pack(4) 改為#pragma pack(16) ,那麼我們可以得到結構的大小為24 。(請讀者自己分析)
關於pragma巨集的具體解釋可以參考:http://baike.baidu.com/view/1451188.html?fromtaglist
**************************分割線*****************************************
可以使用這樣的而乙個巨集來獲得struct成員的偏移量
#define offset(type,member) (size_t)(&(((type)*)0)->(member))
**************************分割線*****************************************
sizeof 用法總結
在vc 中,sizeof 有著許多的用法,而且很容易引起一些錯誤。下面根據sizeof 後面的引數對sizeof 的用法做個總結。
a . 引數為資料型別或者為一般變數。例如sizeof(int),sizeof(long) 等等。這種情況要注意的是不同系統系統或者不同編譯器得到的結果可能是不同的。例如int 型別在16 位系統中佔2 個位元組,在32 位系統中佔4 個位元組。
b . 引數為陣列或指標。下面舉例說明.
c . 引數為結構或類。sizeof 應用在類和結構的處理情況是相同的。但有兩點需要注意,第
一、結構或者類中的靜態成員不對結構或者類的大小產生影響,因為靜態變數的儲存位置與結構或者類的例項位址無關,靜態成員儲存在靜態儲存區中。沒有成員變數的結構或類的大小為1 ,因為必須保證結構或類的每乙個例項在記憶體中都有唯一的位址。下面舉例說明,
class test;//sizeof(test)=4.
test *s;//sizeof(s)=4,s 為乙個指標。
class test1;//sizeof(test1)=1;
d . 引數為其他。下面舉例說明。
int func(char s[5]);
sizeof(func( 「1234 」))=4// 因為func 的返回型別為int ,所以相當於 求sizeof(int).
e .觀察下面程式的輸出
struct struct1;
struct struct2;
struct struct3;
int main(int argc, char* argv)
{cout<
flink批處理中的source以及sink介紹
flink在批處理中常見的source主要有兩大類 1.基於本地集合的source collection based source 2.基於檔案的source file based source 1.基於本地集合的source 在flink最常見的建立dataset方式有三種。1.使用env.fro...
容器容量和容器大小(capacity和size)
1 容器容量 容器所能容納元素的個數,通常大於容器的實際儲存元素的個數。s.capacity 檢視容器容量 s.reserve len 擴充套件當前容器的容量,如果len大於當前容器容量,那麼將會將容器的容量擴充套件為len,且不會對新擴充套件的空間進行初始化 當len小於等於當前容器容量時,什麼也...
C static 以及類的大小
一 整體 countedobject.h ifndef counted object h define counted object h class countedobject endif counted object h countedobject.cpp include countedobjec...