亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

sizeof 用法

系統 1671 0

結構體對齊的具體含義 ( #pragma pack )

#pragma pack (4)
class TestB
{
public:
int aa;
char a;
short b;
char c;
};
int nSize = sizeof(TestB);
  這里 nSize 結果為 12 ,在預料之中。

  現在去掉第一個成員變量為如下代碼:
#pragma pack (4)
class TestC
{
public:
char a;
short b;
char c;
};
int nSize = sizeof(TestC);
  按照正常的填充方式 nSize 的結果應該是 8 ,為什么結果顯示 nSize 6 呢?

事實上,很多人對 #pragma pack 的理解是錯誤的。
#pragma pack
規定的對齊長度,實際使用的規則是:
結構,聯合,或者類的數據成員,第一個放在偏移為 0 的地方,以后每個數據成員的對齊,按照 #pragma pack 指定的數值和這個數據成員自身長度中, 比較小 的那個進行。
也就是說,當 #pragma pack 的值等于或超過所有數據成員長度的時候,這個值的大小將不產生任何效果。
結構整體 的對齊,則按照結構體中最大的數據成員 和 #pragma pack 指定值 之間,較小的那個進行。

具體解釋
#pragma pack (4)
class TestB
{
public:
int aa; // 第一個成員,放在 [0,3] 偏移的位置,
char a; // 第二個成員,自身長為 1 , #pragma pack (4), 取小值,也就是 1 ,所以這個成員按一字節對齊,放在偏移 [4] 的位置。
short b; // 第三個成員,自身長 2 #pragma pack (4) ,取 2 ,按 2 字節對齊,所以放在偏移 [6,7] 的位置。
char c; // 第四個,自身長為 1 ,放在 [8] 的位置。
};
這個類實際占據的內存空間是 9 字節
類之間的對齊, 是按照類內部最大的成員的長度 ,和 #pragma pack 規定的值之中 較小的一個對 齊的。
所以這個例子中,類之間對齊的長度是 min(sizeof(int),4) ,也就是 4 。
9
按照 4 字節圓整的結果是 12 ,所以 sizeof(TestB) 12 。

起始倍數曰對齊,

體內對齊,自身 pra 取小值,

體間對齊,最大 pra 取小值,

體間上取整


如果
#pragma pack (2)
class TestB
{
public:
int aa; // 第一個成員,放在 [0,3] 偏移的位置,
char a; // 第二個成員,自身長為 1 , #pragma pack (4), 取小值,也就是 1 ,所以這個成員按一字節對齊,放在偏移 [4] 的位置。
short b; // 第三個成員,自身長 2 #pragma pack (4) ,取 2 ,按 2 字節對齊,所以放在偏移 [6,7] 的位置。
char c; // 第四個,自身長為 1 ,放在 [8] 的位置。
};
//
可以看出,上面的位置完全沒有變化,只是類之間改為按 2 字節對齊, 9 2 圓整的結果是 10 。
//
所以 sizeof(TestB) 10 。

最后看原貼:
現在去掉第一個成員變量為如下代碼:
#pragma pack (4)
class TestC
{
public:
char a;// 第一個成員,放在 [0] 偏移的位置,
short b;// 第二個成員,自身長 2 , #pragma pack (4) ,取 2 ,按 2 字節對齊,所以放在偏移 [2,3] 的位置。
char c;// 第三個,自身長為 1 ,放在 [4] 的位置。
};
//
整個類的大小是 5 字節,按照 min(sizeof(short),4) 字節對齊,也就是 2 字節對齊,結果是 6
//
所以 sizeof(TestC) 6 。

對於位域有如下規定 :

C99 規定 int 、 unsigned int bool 可以作為位域類型,但編譯器幾乎都對此作了擴展,允許其它類型類型的存在。使用位域的主要目的是壓縮存儲,其大致規則為:
1)
如果相鄰位域字段的類型相同,且其位寬之和小于類型的 sizeof 大小,則后面的字段將緊鄰前一個字段存儲,直到不能容納為止;
2)
如果相鄰位域字段的類型相同,但其位寬之和大于類型的 sizeof 大小,則后面的字段將從新的存儲單元開始,其偏移量為其類型大小的整數倍;
3)
如果相鄰的位域字段的類型不同,則各編譯器的具體實現有差異, VC6 采取不壓縮方式, Dev-C++ 采取壓縮方式;
4)
如果位域字段之間穿插著非位域字段,則不進行壓縮;
5)
整個結構體的總大小為最寬基本類型成員大小的整數倍。

還是讓我們來看看例子。
示例 1
struct BF1
{
char f1 : 3;
char f2 : 4;
char f3 : 5;
};
其內存布局為:
|_f1__|__f2__|_|____f3___|____|
|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
0 3 7 8 1316
位域類型為 char ,第 1 個字節僅能容納下 f1 f2 ,所以 f2 被壓縮到第 1 個字節中,而 f3
能從下一個字節開始。因此 sizeof(BF1) 的結果為 2

示例 2
struct BF2
{
char f1 : 3;
short f2 : 4;
char f3 : 5;
};
由于相鄰位域類型不同,在 VC6 中其 sizeof 6 ,在 Dev-C++ 中為 2 。

示例 3
struct BF3
{
char f1 : 3;
char f2;
char f3 : 5;
};
非位域字段穿插在其中,不會產生壓縮,在 VC6 Dev-C++ 中得到的大小均為 3 。




Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1331903

轉自 :http://rabbitlzx.blogbus.com/logs/2006/03/2094407.html

1 、什么是 sizeof

首先看一下 sizeof msdn 上的定義:

The sizeof keyword gives the amount of storage, in bytes, associated with a variable or a type (including aggregate types). This keyword returns a value of type size_t.

看到 return 這個字眼,是不是想到了函數?錯了, sizeof 不是一個函數,你見過給一個函數傳參數,而不加括號的嗎? sizeof 可以,所以 sizeof 不是函數。網上有人說 sizeof 是一元操作符,但是我并不這么認為,因為 sizeof 更像一個特殊的宏,它是在編譯階段求值的。舉個例子:

cout<<sizeof(int)<<endl; // 32
位機上 int 長度為 4
cout<<sizeof(1==2)<<endl; // ==
操作符返回 bool 類型,相當于 cout<<sizeof(bool)<<endl;

在編譯階段已經被翻譯為:

cout<<4<<endl;
cout<<1<<endl;

這里有個陷阱,看下面的程序:

int a = 0;
cout<<sizeof(a=3)<<endl;
cout<<a<<endl;

輸出為什么是 4 0 而不是期望中的 4 , 3 ???就在于 sizeof 在編譯階段處理的特性。由于 sizeof 不能被編譯成機器碼,所以 sizeof 作用范圍內,也就是 () 里面的內容也不能被編譯,而是被替換成類型。 = 操作符返回左操作數的類型,所以 a=3 相當于 int ,而代碼也被替換為:

int a = 0;
cout<<4<<endl;
cout<<a<<endl;

所以, sizeof 是不可能支持鏈式表達式的,這也是和一元操作符不一樣的地方。

結論:不要把 sizeof 當成函數,也不要看作一元操作符,把他當成一個特殊的編譯預處理。

2 sizeof 的用法

sizeof
有兩種用法:

1 sizeof(object)
也就是對對象使用 sizeof ,也可以寫成 sizeof object 的形式

2 sizeof(typename)
也就是對類型使用 sizeof ,注意這種情況下寫成 sizeof typename 是非法的。下面舉幾個例子說明一下:


int i = 2;
cout<<sizeof(i)<<endl; // sizeof(object)
的用法,合理
cout<<sizeof i<<endl; // sizeof object
的用法,合理
cout<<sizeof 2<<endl; // 2
被解析成 int 類型的 object, sizeof object 的用法,合理
cout<<sizeof(2)<<endl; // 2
被解析成 int 類型的 object, sizeof(object) 的用法,合理
cout<<sizeof(int)<<endl;// sizeof(typename)
的用法,合理
cout<<sizeof int<<endl; //
錯誤!對于操作符,一定要加 ()

可以看出,加 () 是永遠正確的選擇。

結論:不論 sizeof 要對誰取值,最好都加上 () 。


3 、數據類型的 sizeof

1 C++ 固有數據類型

32
C++ 中的基本數據類型,也就 char,short int(short),int,long int(long),float,double, long double
大小分別是: 1 , 2 , 4 , 4 4 8, 10 。

考慮下面的代碼:

cout<<sizeof(unsigned int) == sizeof(int)<<endl; //
相等,輸出 1

unsigned
影響的只是最高位 bit 的意義, 數據長度不會被改變的 。

結論: unsigned 不能影響 sizeof 的取值。

2 )自定義數據類型

typedef
可以用來定義 C++ 自定義類型。考慮下面的問題:

typedef short WORD;
typedef long DWORD;
cout<<(sizeof(short) == sizeof(WORD))<<endl; //
相等,輸出 1
cout<<(sizeof(long) == sizeof(DWORD))<<endl; //
相等,輸出 1

結論:自定義類型的 sizeof 取值等同于它的類型原形。

3 )函數類型

考慮下面的問題:

int f1(){return 0;};
double f2(){return 0.0;}
void f3(){}

cout<<sizeof(f1())<<endl; // f1()
返回值為 int ,因此被認為是 int
cout<<sizeof(f2())<<endl; // f2()
返回值為 double ,因此被認為是 double
cout<<sizeof(f3())<<endl; //
錯誤! 無法對 void 類型使用 sizeof
cout<<sizeof(f1)<<endl; //
錯誤!無法對函數指針使用 sizeof
cout<<sizeof*f2<<endl; // *f2
,和 f2() 等價,因為可以看作 object ,所以括號不是必要的。被認為是 double

結論:對函數使用 sizeof ,在編譯階段會被函數返回值的類型取代。

4
、指針問題

考慮下面問題:

cout<<sizeof(string*)<<endl; // 4
cout<<sizeof(int*)<<endl; // 4
cout<<sizof(char****)<<endl; // 4

可以看到, 不管是什么類型的指針, 大小都是 4 ,因為指針就是 32 位的物理地址。指針存放在 32 位物理地址中

結論:只要是指針,大小就是 4 。( 64 位機上要變成 8 也不一定)。

順便唧唧歪歪幾句, C++ 中的指針表示實際內存的地址。和 C 不一樣的是, C++ 中取消了模式之分,也就是不再有 small,middle,big, 取而代之的是統一的 flat 。 flat 模式采用 32 位實地址尋址,而不再是 c 中的 segment:offset 模式。舉個例子,假如有一個指向地址 f000:8888 的指針,如果是 C 類型則是 8888(16 , 只存儲位移,省略段 ) far 類型的 C 指針是 f0008888(32 位,高位保留段地址,地位保留位移 ),C++ 類型的指針是 f8888(32 位,相當于段地址 *16 + 位移,但尋址范圍要更大 ) 。

5
、數組問題

考慮下面問題:

char a[] = "abcdef";
int b[20] = {3, 4};
char c[2][3] = {"aa", "bb"};


cout<<sizeof(a)<<endl; // 7
cout<<sizeof(b)<<endl; // 80
cout<<sizeof(c)<<endl; // 6


數組 a 的大小在定義時未指定,編譯時給它分配的空間是按照初始化的值確定的,也就是 7 c 是多維數組,占用的空間大小是各維數的乘積,也就是 6 ??梢钥闯?, 數組的大小就是他在編譯時被分配的空間,也就是各維數的乘積 * 數組元素的大小。

結論:數組的大小是各維數的乘積 * 數組元素的大小。

這里有一個陷阱:

int *d = new int[10];

cout<<sizeof(d)<<endl; // 4

d
是我們常說的動態數組,但是他實質上還是一個指針,所以 sizeof(d) 的值是 4 。

再考慮下面的問題:

double* (*a)[3][6];

cout<<sizeof(a)<<endl; // 4
cout<<sizeof(*a)<<endl; // 72
cout<<sizeof(**a)<<endl; // 24
cout<<sizeof(***a)<<endl; // 4
cout<<sizeof(****a)<<endl; // 8

a
是一個很奇怪的定義,他表示一個指向 double*[3][6] 類型數組的指針。既然是指針,所以 sizeof(a) 就是 4

既然 a 是執行 double*[3][6] 類型的指針, *a 就表示一個 double*[3][6] 的多維數組類型,因此 sizeof(*a)=3*6*sizeof(double*)=72 。同樣的, **a 表示一個 double*[6] 類型的數組,所以 sizeof(**a)=6*sizeof(double*)=24 。 ***a 就表示其中的一個元素,也就是 double* 了,所以 sizeof(***a)=4 。至于 ****a ,就是一個 double 了,所以 sizeof(****a)=sizeof(double)=8 。


6
、向函數傳遞數組的問題

考慮下面的問題:
#include <iostream>
using namespace std;

int Sum(int i[])
{
int sumofi = 0;
for (int j = 0; j < sizeof(i)/sizeof(int); j++) //
實際上, sizeof(i) = 4
{
sumofi += i[j];
}
return sumofi;
}

int main()
{
int allAges[6] = {21, 22, 22, 19, 34, 12};
cout<<Sum(allAges)<<endl;
system("pause");
return 0;
}

Sum
的本意是用 sizeof 得到數組的大小,然后求和。但是實際上,傳入自函數 Sum 的,只是一個 int 類型的指針,所以 sizeof(i)=4 ,而不是 24 ,所以會產生錯誤的結果。解決這個問題的方法使是用指針或者引用。

使用指針的情況:
int Sum(int (*i)[6])
{
int sumofi = 0;
for (int j = 0; j < sizeof(*i)/sizeof(int); j++) //sizeof(*i) = 24
{
sumofi += (*i)[j];
}
return sumofi;
}

int main()
{
int allAges[] = {21, 22, 22, 19, 34, 12};
cout<<Sum(&allAges)<<endl;
system("pause");
return 0;
}
在這個 Sum 里, i 是一個指向 i[6] 類型的指針,注意,這里不能用 int Sum(int (*i)[]) 聲明函數,而是 必須指明要傳入的數組的大小, 不然 sizeof(*i) 無法計算。但是在這種情況下,再通過 sizeof 來計算數組大小已經沒有意義了,因為此時大小是指定為 6 的。
使用引用的情況和指針相似:

int Sum(int (&i)[6])
{
int sumofi = 0;
for (int j = 0; j < sizeof(i)/sizeof(int); j++)
{
sumofi += i[j];
}
return sumofi;
}

int main()
{
int allAges[] = {21, 22, 22, 19, 34, 12};
cout<<Sum(allAges)<<endl;
system("pause");
return 0;
}
這種情況下 sizeof 的計算同樣無意義,所以用數組做參數,而且需要遍歷的時候,函數應該有一個參數來說明數組的大小,而數組的大小在數組定義的作用域內通過 sizeof 求值。因此上面的函數正確形式應該是:
#include <iostream>
using namespace std;

int Sum(int *i, unsigned int n)
{
int sumofi = 0;
for (int j = 0; j < n; j++)
{
sumofi += i[j];
}
return sumofi;
}

int main()
{
int allAges[] = {21, 22, 22, 19, 34, 12};
cout<<Sum(i, sizeof(allAges)/sizeof(int))<<endl;
system("pause");
return 0;
}

7
、字符串的 sizeof strlen

考慮下面的問題:

char a[] = "abcdef";
char b[20] = "abcdef";
string s = "abcdef";

cout<<strlen(a)<<endl; // 6
,字符串長度
cout<<sizeof(a)<<endl; // 7
,字符串容量
cout<<strlen(b)<<endl; // 6
,字符串長度
cout<<strlen(b)<<endl; // 20
,字符串容量
cout<<sizeof(s)<<endl; // 12,
這里不代表字符串的長度,而是 string 類的大小
cout<<strlen(s)<<endl; //
錯誤! s 不是一個字符指針。

a[1] = '';
cout<<strlen(a)<<endl; // 1
cout<<sizeof(a)<<endl; // 7
, sizeof 是恒定的 因空間已開辟


strlen
是尋找從指定地址開始,到出現的第一個 0 之間的字符個數,他是在運行階段執行的,而 sizeof 是得到數據的大小,在這里是得到字符串的容量。 所以對同一個對象而言, sizeof 的值是恒定的。 string C++ 類型的字符串,他是一個類,所以 sizeof(s) 表示的并不是字符串的長度,而是類 string 的大小。 strlen(s) 根本就是錯誤的,因為 strlen 的參數是一個字符指針,如果想用 strlen 得到 s 字符串的長度,應該使用 sizeof(s.c_str()) ,因為 string 的成員函數 c_str() 返回的是字符串的首地址。實際上, string 類提供了自己的成員函數來得到字符串的容量和長度,分別是 Capacity() Length() 。 string 封裝了常用了字符串操作,所以在 C++ 開發過程中,最好使用 string 代替 C 類型的字符串。


8
、從 union sizeof 問題看 cpu 的對界

考慮下面問題:(默認對齊方式)

union u
{
double a;
int b;
};

union u2
{
char a[13];
int b;
};

union u3
{
char a[13];
char b;
};

cout<<sizeof(u)<<endl; // 8
cout<<sizeof(u2)<<endl; // 16
cout<<sizeof(u3)<<endl; // 13

都知道 union 的大小取決于它所有的成員中,占用空間最大的一個成員的大小。所以對于 u 來說,大小就是最大的 double 類型成員 a 了,所以 sizeof(u)=sizeof(double)=8 。但是對于 u2 u3 ,最大的空間都是 char[13] 類型的數組,為什么 u3 的大小是 13 ,而 u2 16 呢?關鍵在于 u2 中的成員 int b 。由于 int 類型成員的存在,使 u2 的對齊方式變成 4 ,也就是說, u2 的大小必須在 4 的對界上 ( 4 的倍數 ) ,所以占用的空間變成了 16 (最接近 13 的對界)。

結論:復合數據類型,如 union , struct , class 的對齊方式為成員中對齊方式 最大的成員 的對齊方式。

順便提一下 CPU 對界問題, 32 C++ 采用 8 位對界來提高運行速度,所以編譯器會盡量把數據放在它的對界上以提高內存命中率。對界是可以更改的,使用 #pragma pack(x) 宏可以改變編譯器的對界方式, 默認是 8 。 C++ 固有類型的對界取 編譯器對界方式與自身大小中較小的一個 。例如,指定編譯器按 2 對界, int 類型的大小是 4 ,則 int 的對界為 2 4 中較小的 2 。在默認的對界方式下,因為幾乎所有的數據類型都不大于默認的對界方式 8 (除了 long double ),所以所有的固有類型的對界方式可以認為就是類型自身的大小。更改一下上面的程序:

#pragma pack(2)
union u2
{
char a[13];
int b;
};

union u3
{
char a[13];
char b;
};
#pragma pack(8)

cout<<sizeof(u2)<<endl; // 14
cout<<sizeof(u3)<<endl; // 13

由于手動更改對界方式為 2 ,所以 int 的對界也變成了 2 , u2 的對界取成員中最大的對界 ,也是 2 了,所以此時 sizeof(u2)=14

結論: C++ 固有類型的對界取編譯器對界方式與自身大小中較小的一個。

9 、 struct sizeof 問題

因為對齊問題使結構體的 sizeof 變得比較復雜,

看下面的例子: ( 默認對齊方式下 )

struct s1{

char a;

double b;

int c;

char d;

};

struct s2{

char a;

char b;

int c;

double d;

};

cout<<sizeof(s1)<<endl; // 24

cout<<sizeof(s2)<<endl; // 16

同樣是兩個 char 類型,一個 int 類型,一個 double 類型,但是

因為對界問題,導致他們的大小不同。計算結構體大小可以采用

元素擺放法,我舉例子說明一下:首先, CPU 判斷結構體的對界,

根據上一節的結論, s1 s2 的對界都取最大的元素類型,也就是

double 類型的對界 8 。然后開始擺放每個元素。

對于 s1 ,首先把 a 放到 8 的對界,假定是 0 ,此時下一個空閑的地址

1 ,但是下一個元素 b double 類型,要放到 8 的對界上,離 1

最接近的地址是 8 了,所以 b 被放在了 8 ,此時下一個空閑地址變成

16 ,下一個元素 c 的對界是 4 16 可以滿足,所以 c 放在了 16

此時下一個空閑地址變成了 20 ,下一個元素 d 需要對界 1 ,也正好

落在對界上,所以 d 放在了 20 ,結構體在地址 21 處結束。由于 s1

大小需要是 8 的倍數 ,所以 21-23 的空間被保留, s1 的大小變成

24 。

對于 s2 ,首先把 a 放到 8 的對界,假定是 0 ,此時下一個空閑地址

1 ,下一個元素的對界也是 1 ,所以 b 擺放在 1 ,下一個空閑地址

變成了 2 ;下一個元素 c 的對界是 4 ,所以取離 2 最近的地址 4 擺放 c( 4 個字節作一個單位,第一個單位已被占用 ) ,

下一個空閑地址變成了 8 ,下一個元素 d 的對界是 8 ,所以 d 擺放在 8 ,

所有元素擺放完畢,結構體在 15 處結束,占用總空間為 16 ,正好

8 的倍數。

這里有個陷阱,對于結構體中的結構體成員,不要認為它的

對齊方式就是他的大小,看下面的例子:

struct s1{

char a[8];

};

struct s2{

double d;

};

struct s3{

s1 s;

char a;

};

struct s4{

s2 s;

char a;

};

cout<<sizeof(s1)<<endl; // 8

cout<<sizeof(s2)<<endl; // 8

cout<<sizeof(s3)<<endl; // 9

cout<<sizeof(s4)<<endl; // 16;

s1 s2 大小雖然都是 8 ,但是 s1 的對齊方式是 1 , s2 8 double ),

所以在 s3 s4 中才有這樣的差異。所以,在自己定義結構體的時候,如果空間緊張的話,最好考慮

對齊因素來排列結構體里的元素。

10 、不要讓 double 干擾你的位域

在結構體和類中,可以使用位域來規定某個成員所能占用的空間,

所以 使用位域能在一定程度上節省結構體占用的空間 。

不過考慮下面的代碼:

struct s1{

int i: 8;

int j: 4;

double b;

int a:3;

};

struct s2{

int i;

int j;

double b;

int a;

};

struct s3{

int i;

int j;

int a;

double b;

};

struct s4{

int i: 8;

int j: 4;

int a:3;

double b;

};

cout<<sizeof(s1)<<endl; // 24

cout<<sizeof(s2)<<endl; // 24

cout<<sizeof(s3)<<endl; // 24

cout<<sizeof(s4)<<endl; // 16

可以看到,有 double 存在會干涉到位域( sizeof 的算法參考上

一節),所以使用位域的的時候,最好把 float 類型和 double

類型放在程序的 開始或者最后 。

------------------------------------------------------------

------------------------------------------------------------

sizeof 在求結構大小時的使用及 sizeof 主要用法
Tag:
program

本文主要包括二個部分,第一部分重點介紹在 VC 中,怎么樣采用 sizeof 來求結構的大小,以及容易出現的問題,并給出解決問題的方法,第二部分總結出 VC sizeof 的主要用法。

1 、 sizeof 應用在結構上的情況

請看下面的結構:

struct MyStruct

{

double dda1;

char dda;

int type

};


對結構 MyStruct 采用 sizeof 會出現什么結果呢? sizeof(MyStruct) 為多少呢?也許你會這樣求:

sizeof(MyStruct)=sizeof(double)+sizeof(char)+sizeof(int)=13

但是當在 VC 中測試上面結構的大小時,你會發現 sizeof(MyStruct) 16 。你知道為什么在 VC 中會得出這樣一個結果嗎?

其實,這是 VC 對變量存儲的一個特殊處理。 為了提高 CPU 的存儲速度, VC 對一些變量的起始地址做了 對齊 處理。 在默認情況下, VC 規定各成員變量存放的起始地址相對于結構的起始地址的偏移量必須為該變量的類型所占用的字節數的倍數。下面列出常用類型的對齊方式 (vc6.0,32 位系統 ) 。

類型
對齊方式(變量存放的起始地址相對于結構的起始地址的偏移量)

Char
偏移量必須為 sizeof(char) 1 的倍數

int
偏移量必須為 sizeof(int) 4 的倍數

float
偏移量必須為 sizeof(float) 4 的倍數

double
偏移量必須為 sizeof(double) 8 的倍數

Short
偏移量必須為 sizeof(short) 2 的倍數




各成員變量在存放的時候根據在結構中出現的順序依次申請空間,同時按照上面的對齊方式調整位置,空缺的字節 VC 會自動填充。同時 VC 為了確保結構的大小為結構的字節邊界數(即該結構中占用最大空間的類型所占用的字節數)的倍數,所以在為最后一個成員變量申請空間后,還會根據需要自動填充空缺的字節

下面用前面的例子來說明 VC 到底怎么樣來存放結構的。

struct MyStruct

{

double dda1;

char dda;

int type

}
;

為上面的結構分配空間的時候, VC 根據成員變量出現的順序和對齊方式,先為第一個成員 dda1 分配空間,其起始地址跟結構的起始地址相同(剛好偏移量 0 剛好為 sizeof(double) 的倍數),該成員變量占用 sizeof(double)=8 個字節;接下來為第二個成員 dda 分配空間,這時下一個可以分配的地址對于結構的起始地址的偏移量為 8 ,是 sizeof(char) 的倍數,所以把 dda 存放在偏移量為 8 的地方滿足對齊方式,該成員變量占用 sizeof(char)=1 個字節;接下來為第三個成員 type 分配空間,這時下一個可以分配的地址對于結構的起始地址的偏移量為 9 ,不是 sizeof(int)=4 的倍數,為了滿足對齊方式對偏移量的約束問題, VC 自動填充 3 個字節(這三個字節沒有放什么東西),這時下一個可以分配的地址對于結構的起始地址的偏移量為 12 ,剛好是 sizeof(int)=4 的倍數,所以把 type 存放在偏移量為 12 的地方,該成員變量占用 sizeof(int)=4 個字節;這時整個結構的成員變量已經都分配了空間,總的占用的空間大小為: 8+1+3+4=16 ,剛好為結構的字節邊界數(即結構中占用最大空間的類型所占用的字節數 sizeof(double)=8 )的倍數,所以沒有空缺的字節需要填充。所以整個結構的大小為: sizeof(MyStruct)=8+1+3+4=16 ,其中有 3 個字節是 VC 自動填充的,沒有放任何有意義的東西。

下面再舉個例子,交換一下上面的 MyStruct 的成員變量的位置,使它變成下面的情況:

struct MyStruct

{

char dda;

double dda1;

int type

}
;

這個結構占用的空間為多大呢?在 VC6.0 環境下,可以得到 sizeof(MyStruc) 24 。結合上面提到的分配空間的一些原則,分析下 VC 怎么樣為上面的結構分配空間的。(簡單說明)

struct MyStruct

{

char dda;//
偏移量為 0 ,滿足對齊方式, dda 占用

分享到:
評論
wapysun
  • 瀏覽: 4881624 次
  • 性別: Icon_minigender_1
  • 來自: 杭州
最新評論

sizeof 用法


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。?!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 四虎免费影院4hu永久免费 | 婷婷色九月 | 中文字幕色综合久久 | 色狠狠色综合吹潮 | 在线 色| 国内精品综合九九久久精品 | 天天干狠狠操 | 草久在线观看视频 | 欧美一级黄色录像 | 久久噜| 天天插天天舔 | 久久青草免费线观最新 | 日本色图网站 | 天天夜夜骑 | 天天曰天天爽 | 亚洲成色综合一区二区三区四区 | 午夜一级 | 男任天堂2021 | 久久手机免费视频 | 天天操天天摸天天爽 | 高清国产精品久久久久 | 国产乳摇福利视频在线观看 | 四虎影院最新 | 亚洲欧洲精品成人久久曰 | 国产精品亚洲欧美 | 久久久久国产精品免费看 | 成人a一级毛片免费看 | 91成人在线播放 | 日本三级日本三级人妇三级四 | 日日舔夜夜操 | 国产日韩精品一区二区在线观看 | 顶级欧美色妇xxxxbbbb | 操操操日日 | 久久免费视频99 | 亚洲乱码中文字幕 | 青青草免费在线视频 | 久久久久久穴 | 91青草久久久久久清纯 | 欧美激情社区 | 成年女人毛片免费播放人 | 男人草女人视频 |