全面解析sizeof(下),全面解析sizeof(

來源:互聯網
上載者:User

全面解析sizeof(下),全面解析sizeof(

以下代碼使用平台是Windows7 64bits+VS2012。

sizeof作用於基礎資料型別 (Elementary Data Type),在特定的平台和特定的編譯中,結果是確定的,如果使用sizeof計算構造類型:結構體、聯合體和類的大小時,情況稍微複雜一下。

1.sizeof計算結構體

考察如下代碼:

struct S1{    char c;    int i;};cout<<”sizeof(S1)=”<<sizeof(S1)<<endl;

sizeof(S1)結果是8,並不是想象中的sizeof(char)+sizeof(int)=5。這是因為結構體或者類成員變數具有不同類型時,需要進程成員變數的對齊,電腦群組成原理中說明,對齊的目的是減少訪存指令周期,提高CPU儲存速度。

1.1記憶體對齊的原則

(1)結構體變數的首地址能夠被其最寬基本類型成員的大小所整除;
(2)結構體每個成員相對於結構體首地址的位移量都是成員大小的整數倍,如有需要編譯器會在成員之間加上填充位元組;
(3)結構體的總大小為結構體最寬基本類型成員大小的整數倍,如有需要編譯器會在最末一個成員之後加上填充位元組。有了以上三個記憶體對齊的原則,就可以輕鬆應對嵌套結構體類型的記憶體對齊。如下:

struct S2{    char c1;    S1 s;    char c2};

在尋找S2的最寬基礎資料型別 (Elementary Data Type)時,包括其嵌套的結構體中的成員,從S1中尋找出最寬結構體資料類型是int,因此S2的最寬資料類型是int。S1 s在結構體S2中的對齊也是按前面三個準則進行,因此sizeof(S2)=sizeof(char)+pad(3)+sizeof(S1)+1+pad(3)=1+3+8+1+3=16位元組,其中pad(3)表示填充3個位元組。
結構體某個成員相對於結構體首地址的位移量可以通過宏offsetof()來獲得,這個宏也在stddef.h中定義,如下:
#define offsetof(s,m) (size_t)&(((s *)0)->m)
例如,想要獲得S2中c的位移量,方法為
size_t pos = offsetof(S2, c); // pos等於4

1.2預先處理編譯器指導指令#pragma pack

#pragma pack( n ),n為位元組對齊數,其取值為1、2、4、8、16,預設是8,表明最寬資料類型不超過8。如果這個值比結構體成員的sizeof值小,那麼該成員的位移量應該以此值為準,即是說,結構體成員的位移量應該取二者的最小值,公式如下:
offsetof( item ) = min( n, sizeof( item ) )。
考察如下代碼:

#pragma pack(push) // 將當前pack設定壓棧儲存#pragma pack(2) // 必須在結構體定義之前使用struct S1{    char c;    int i;};struct S2{    char c1;    S1 s;    char c2};#pragma pack(pop) // 恢複先前的pack設定

因此,sizeof(S2)=sizeof(char)+pad(1)+sizeof(S1)+1+pad(1)=1+1+6+1=10位元組。

1.3空結構體

C/C++中不允許長度為0的資料類型存在。對於“空結構體”(不含資料成員)的大小不為0,而是1。“空結構體”變數也得被儲存,這樣編譯器也就只能為其分配一個位元組的空間用於佔位了。如下:

struct S3 { };sizeof( S3 ); // 結果為1
1.4位域結構體

有些資訊在儲存時,並不需要佔用一個完整的位元組, 而只需占幾個或一個二進位位。例如在存放一個開關量時,只有0和1 兩種狀態, 用一位二進位即可。為了節省儲存空間,並使處理簡便,C語言又提供了一種資料結構,稱為”位域”或”位段”。以位域變數成員變數結構體的叫做位域結構體。
位域結構體的定義形式:
struct 位域結構名
{ 位域列表 };
位域列表的形式為: 類型說明符 位網域名稱:位域長度。
使用位域的主要目的是壓縮儲存,其大致規則為:
(1) 如果相鄰位域欄位的類型相同,且其位寬之和小於類型的sizeof大小,則後面的欄位將緊鄰前一個欄位儲存,直到不能容納為止;
(2) 如果相鄰位域欄位的類型相同,但其位寬之和大於類型的sizeof大小,則後面的欄位將從新的儲存單元開始,其位移量為其類型大小的整數倍;
(3) 如果相鄰的位域欄位的類型不同,則各編譯器的具體實現有差異,VC6採取不壓縮方式,Dev-C++採取壓縮方式;
(4) 如果位域欄位之間穿插著非位域欄位,則不進行壓縮;
(5) 整個結構體的總大小為最寬基本類型成員大小的整數倍。
(6)位域可以無位網域名稱,這時它只用來作填充或調整位置。無名的位域是不能使用的。
例如:

struct k {     int a:1     int :2 //該2位不能使用    int b:3 int c:2 };

考察如下代碼:

struct BFS1{    char f1 : 3;    char f2 : 4;    char f3 : 5;};struct BFS2{    char f1 : 3;    int i : 4;    char f2 : 5;};struct BFS3{    char f1 : 3;    char f2;    char f3 : 5;};

考察以上代碼,得出:
(1)sizeof(BFS1)==2。當相鄰位域類型不同,在VS中其sizeof(BFS2)=1+4+1+pad(2)=8,位域變數i的位移量無需是4的倍數,緊隨f1的後一位元組儲存,但位域結構體BFS2的總大小必須是sizeof(int)的整數倍。在Dev-C++中為sizeof(BFS2)=2,相鄰的位域欄位的類型不同時,採取了壓縮儲存。
(2)sizeof(BFS3)==3,當非位域欄位穿插在其中,不會產生壓縮,在VS和Dev-C++中得到的大小均為3。

2.sizeof計算聯合體

結構體在記憶體組織上是順序式的,聯合體則是重疊式,各成員共用一段記憶體,所以整個聯合體的sizeof也就是每個成員sizeof的最大值。結構體的成員也可以是構造類型,這裡,構造類型成員是被作為整體考慮的。所以,下面例子中,U的sizeof值等於sizeof(s)。

union U{    int i;    char c;    S1 s;};
3.sizeof計算類

考察如下代碼:

#include <iostream>using namespace std;class Small{};class LessFunc{int num;void func1(){};};class MoreFunc{int num;void func1(){};int func2(){return 1;};};class NeedAlign{char c;double d;int i;};class Virtual{int num;virtual void func(){};};int main(int argc,char* argv[]){    cout<<sizeof(Small)<<endl;   //輸出1    cout<<sizeof(LessFunc)<<endl;//輸出4    cout<<sizeof(MoreFunc)<<endl;//輸出4    cout<<sizeof(NeedAlign)<<endl;//輸出24    cout<<sizeof(Virtual)<<endl; //輸出8    return 0;}

注意一點,C++中類同結構體沒有本質的區別,結構體同樣可以包含成員函數,建構函式,解構函式,虛函數和繼承,但一般不這麼使用,沿用了C的結構體使用習慣。類與結構體唯一的區別就是結構體的成員的預設許可權是public,而類是private。
基於以上這點,再考察從程式的輸出結果,得出如下結論:
(1)類同結構體一樣,C++中不允許長度為0的資料類型存在,雖然類無任何成員,但該類的對象仍然佔用1個位元組。
(2)類的成員函數並不影響類對象佔用的空間,類對象的大小是由它資料成員決定的。
(3)類和結構體一樣,同樣需要對齊,具體對齊的規則見上文結構體的記憶體對齊。
(4)類如果包含虛函數,編譯器會在類對象中插入一個指向虛函數表的指標,以協助實
現虛函數的動態調用。所以,該類的對象的大小至少比不包含虛函數時多4個位元組。如果考慮記憶體對齊,可能還要多些。如果使用資料成員之間的對齊,當類對象至少包含一個資料成員,且擁有虛函數,那麼該對象的大小至少是8B,讀者可自行推導。

參考文獻

[1]陳剛.C++進階進階教程[M].武漢:武漢大學出版社,2008.
[2]http://blog.csdn.net/freefalcon/article/details/54839

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.