深入理解計算機各種型別大小(sizeof)

2021-07-05 18:57:21 字數 4314 閱讀 3557

int a;

sizeof(a); // = 4

sizeof(int); // = 4

sizeof(1); // = 4

void fn() 

sizeof(fn); // error:函式

sizeof(fn()); // error:不能確定型別

struct s

; s sa;

sizeof( sa.a ); // error:位域成員

int a = -1;

sizeof(a=3); // = sizeof(a) = sizeof(int) = 4

cout<

sizeof(int); // = 4

sizeof(double); // = 8

sizeof(char); // = 1

sizeof(bool); // = 1

sizeof(short); // = 2

sizeof(float); // = 4

sizeof(long); // = 4

sizeof(int *);         // = 4

sizeof(double *); // = 4

sizeof(char *); // = 4

2.3.1 陣列的sizeof返回整個陣列所佔的位元組數,即(陣列元素個數×每個元素所佔位元組)。
int ai = ;

sizeof(ai); // = 2*4 = 8

2.3.2 常量字串與字元陣列的記憶體分配方式相同。

char ac = "abcd";  //注意陣列末尾的字串終結符'\0'

sizeof(ac); // = 5*1 = 5

sizeof("abcd"); // = 5*1 = 5

2.3.3 陣列和指標所佔的位元組數不同,應注意區分。
int *pi = new int[10]; //這是指標

sizeof(pi); // = 4

int ai[10];

int *p = ai; //這還是指標

sizeof(p); // = 4

double* (*a)[3][6]; //看成(double *) (*a)[3][6],即乙個3×6的二維陣列,陣列元素為指標,指向double型別。

sizeof(a); // = 4,a為指向上述二維陣列的指標

sizeof(*a); // = sizeof(double *)*3*6 = 72,*a表示上述二維陣列

sizeof(**a); // = sizeof(double *)*6 = 24,**a即*(*a),表示double*[6],是元素為double指標的一維陣列。

sizeof(***a); // = sizeof(double *) = 4,表示上述一維陣列中的第乙個元素,元素型別為double指標。

sizeof(****a); // = sizeof(double) = 8,表示上述陣列首元素指向的double型別。

2.3.4 函式形式引數中的陣列會蛻變為指標,原因是陣列引數「傳址呼叫」,呼叫者只需將實參的位址傳遞過去。有一種情況例外,那就是引數是指向陣列的指標。
void acf(char p[3])     //引數型別是int,表示指向int的指標

void aif(int p) //引數型別是int,表示指向int的指標

void pif(int (*p)[6]) //引數型別是int (*)[6],表示指向int陣列的指標

void ppf(int *p[6]) //引數型別是int *,表示指向int指標的指標

2.4.1 空類或空結構體占乙個位元組。
class cempty ;

sizeof(cempty); // = 1

struct sempty ;

sizeof(sempty); // = 1

2.4.2 非空類和結構體所佔位元組為所有成員佔位元組的和,但是不包括成員函式和靜態成員所佔的空間。

class cint : public cempty ;

sizeof(cint); // = 4;

class cfunc

};sizeof(cfunc); // = 1;

struct sint : sempty ;

sizeof(sint); // = 1;

2.4.3 位元組對齊

為了加快計算機的取數速度,編譯器預設對記憶體進行位元組對齊。對結構體(包括類)進行位元組對齊的原則是:

1)結構體變數的首位址能夠被其最寬基本型別成員的大小所整除;

2)結構體每個成員相對於結構體首位址的偏移量(offset)都是成員大小的整數倍,如有需要編譯器會在成員之間加上填充位元組(internal adding);

3)結構體的總大小為結構體最寬基本型別成員大小的整數倍,如有需要編譯器會在最末乙個成員之後加上填充位元組(trailing padding)。

struct sbyte1

; sizeof(sbyte1); // = 16

struct sbyte2

; sizeof(sbyte2); // = 24,為了湊成8的倍數,填充20~23

另外,可以通過#pragma pack(n)來設定變數以n位元組對齊方式。
#pragma pack(push) //儲存對齊狀態

#pragma pack(4) //設定為4位元組對齊

class cbyte

;#pragma pack(pop) //恢復對齊狀態

sizeof(cbyte); // = 16

2.4.4 位域

有些資訊在儲存時,並不需要占用乙個完整的位元組, 而只需佔幾個或乙個二進位制位。例如在存放乙個開關量時,只有0和1 兩種狀態,用一位二進位即可。為了節省儲存空間,並使處理簡便,c語言又提供了一種資料結構,稱為「位域」或「位段」。所謂「位域」是把乙個位元組中的二進位劃分為幾個不同的區域, 並說明每個區域的位數。 

2.4.4.1 位域以位元位作為單位,其長度不能大於乙個位元組。乙個位域必須儲存在同乙個位元組中,如乙個位元組所剩空間不夠存放另一位域時,應從下一單元起存放該位域。

struct sbit1

;sizeof(sbit1); // = (3+4+1+5+3) bits = 2 bytes

2.4.4.2 使用空域可以有意使某位域從下一單元開始,但是空域不能使用。

sizeof(sbit2); // = (3+4+1+5+3) bits = 3 bytes

struct sbit2

;sizeof(sbit2); // = (3+4+1+5+3) bits = 3 bytes

2.4.4.3 如果相鄰的位域字段的型別不同,則各編譯器的具體實現有差異,vc6採取不壓縮方式,dev-c++採取壓縮方式。
struct sbit3

;sizeof(sbit3); // = 6 bytes,由於相鄰位域型別不同,在vc6中其sizeof為6,在dev-c++中為2。

2.4.4.4 如果位域字段之間穿插著非位域字段,則不進行壓縮。
struct sbit4

;sizeof(sbit4); // = 8 bytes

2.4.4.5 整個結構體的總大小為最寬基本型別成員大小的整數倍
;

sizeof(sbit5); // = 12 bytes

聯合表示若干資料成員取其一,故以疊加方式分配記憶體,所佔位元組數為最大資料成員所佔的位元組數。

cpp**

union u   

;   

sizeof(u); // = max(sizeof(i), sizeof(c), sizeof(d)) = sizeof(d) = 8

計算機深入理解 一

1.1 匯流排 匯流排是用來在計算機各個部件中傳遞資料的快遞員,這個快遞員攜帶的資料是有限制的通常是4個位元組32位,8個位元組64位。1.2 io 裝置 io 裝置是計算機與外界資料交換的快遞員。包括四個功能不一的快遞員 1 作為使用者輸入的鍵盤和滑鼠 2 作為使用者輸出的顯示器 3 用來長期儲存...

深入理解計算機筆記1

第一章 本書可以使你成為鳳毛麟角的權威程式設計師。1系統中的所有資訊都是由一串二進位制表示的,區分不同資料物件的唯一方法是我們讀到這些資料物件時的上下文。比如10000110,可以是乙個無符號數,也可以是乙個有符號數,還可以是乙個ascii碼,還可能是一條指令。2編譯系統包括了預處理器 編譯器 彙編...

深入理解計算機系統

關鍵路徑是在迴圈的反覆執行中形成的資料相關鏈。迴圈展開是一種程式變換,通過增加每次迭代計算的元素的數量,減少迴圈的迭代次數。重新結合變換能夠減少計算中關鍵路徑上操作的數量,通過更好地利用功能單元的流水線能力得到更好的效能。浮點運算不保證是可結合的,通常迴圈展開和並行地累積在多個值中,是提高程式效能的...