記憶體總結之返回物件占用位元組數操作符sizeof

2021-09-12 11:58:20 字數 3683 閱讀 7554

申明:sizeof() 是乙個判斷資料型別或者表示式長度的運算子。sizeof() 的處理都是在編譯階段進行。其作用就是返回乙個物件或者型別所佔的記憶體位元組數。

但是sizeof(void)是非法的,沒有人會定義乙個void變數,void真正發揮的作用在於:對函式返回的限定;對函式引數的限定。

visual studio 2017上void a;//顯示不允許使用不完整的型別,並且會報錯c2182,非法使用"void"型別。

1、32位系統為4,64位系統則為8。

2、所有的指標變數所佔記憶體大小相等,因為指標變數的sizeof值與指標所指的物件沒有任何關係。

1、列舉型別,本質上是一組常數的集合體,只是這些常數有各自的命名。列舉型別,是一種使用者自定義資料型別。

2、列舉變數,由列舉型別定義的變數。列舉變數的大小,即列舉型別所佔記憶體的大小。由於列舉變數的賦值,一次只能存放列舉結構中的某個常數。所以列舉變數的大小,實質是常數所佔記憶體空間的大小,列舉型別所佔記憶體大小也是這樣。

1、陣列的sizeof值等於陣列所占用的記憶體位元組數==元素型別大小*元素個數。

2、當字元陣列表示字串時,其sizeof值將』/0』計算進去。

3、陣列名作為實參傳入函式時,會自動轉化為指標型別,所以其sizeof值相當於指標的sizeof值。

1、聯合體union性質

a、聯合體所有成員變數共享記憶體,相對於聯合體首位址偏移量都為0。

b、同一時間只能儲存1個被選擇的變數,對其他成員變數賦值會覆蓋原變數。

2.聯合體大小計算準則

a、聯合體大小要至少能容納最大的成員變數。

b、復合資料型別,如union、struct、class的對齊方式為成員中最大的成員對齊方式。(陣列可以理解為多個相同成員的集合)。

3、對齊是可以更改的,使用#pragma pack(x)可以改變編譯器的對其方式。

1、結構體的sizeof涉及到位元組對齊問題。

為什麼需要位元組對齊?計算機組成原理教導我們這樣有助於加快計算機的取數速度,否則就得多花指令週期了。為此,編譯器缺省會對結構體進行處理(實際上其它地方的資料變數也是如此),讓寬度為2的基本資料型別(short等)都位於能被2整除的位址上,讓寬度為4的基本資料型別(int等)都位於能被4整除的位址上,依次類推。這樣,兩個數中間就可能需要加入填充位元組,所以整個結構體的sizeof值就增長了。

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

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

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

注意:空結構體(不含資料成員)的sizeof值為1。試想乙個「不佔空間「的變數如何被取位址、兩個不同的「空結構體」變數又如何得以區分呢,於是,「空結構體」變數也得被儲存,這樣編譯器也就只能為其分配乙個位元組的空間用於佔位了。

d、c99規定int、unsigned int和bool可以作為位域型別,但編譯器幾乎都對此作了擴充套件,允許其它型別型別的存在。使用位域的主要目的是壓縮儲存,其大致規則為:

(1)如果相鄰位域字段的型別相同,且其位寬之和小於型別的sizeof大小,則後面的字段將緊鄰前乙個字段儲存,直到不能容納為止

(2)如果相鄰位域字段的型別相同,但其位寬之和大於型別的sizeof大小,則後面的字段將從新的儲存單元開始,其偏移量為其型別大小的整數倍。

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

(4)如果位域字段之間穿插著非位域字段,則不進行壓縮。

(5)整個結構體的總大小為最寬基本型別成員大小的整數倍。

還是讓我們來看看例子。

示例1:

struct bf1;

其記憶體布局為:

位域型別為char,第1個位元組僅能容納下f1和f2,所以f2被壓縮到第1個位元組中,而f3只能從下乙個位元組開始。因此sizeof(bf1)的結果為2。

示例2:

struct bf2;

由於相鄰位域型別不同,在vc6中其sizeof為3,在dev-c++中為2。

示例3:

struct bf3;

非位域字段穿插在其中,不會產生壓縮,在vc6和dev-c++中得到的大小均為3。

1、c++中類所佔的大小計算涉及到虛函式成員,靜態成員,虛繼承,多繼承以及空類等。

2、宣告的類只是一種型別定義,它本身是沒有大小可言的。這裡指的類的大小,其實指的是類的物件所佔的大小。

3、關於類/物件大小的計算

a、首先,類大小的計算遵循結構體的對齊原則

b、類的大小與普通資料成員有關,與成員函式和靜態成員無關。

d、即普通成員函式,靜態成員函式,靜態資料成員,靜態常量資料成員均對類的大小無影響。

e、虛函式對類的大小有影響,是因為虛函式表指標帶來的影響。

f、虛繼承對類的大小有影響,是因為虛基表指標帶來的影響

g、空類的大小是乙個特殊情況,空類的大小為1

4、sizeof求stl中的string類的物件所佔的記憶體位元組數

visual studio中普遍是28位元組,vc 6.0算出來的是16位元組,有些書上是4位元組。

1、strlen(char*)函式求的是字串的實際長度,直到遇到第乙個』\0』,然後就返回計數值,且不包括』\0』。而sizeof()函式返回的是變數宣告後所佔的記憶體數,不是實際長度。

2、sizeof是運算子,strlen是函式。

3、sizeof可以用型別做引數,strlen只能用char*做引數,且必須是以』』\0』'結尾的;sizeof還可以用函式做引數。

4、陣列做sizeof的引數不退化,傳遞給strlen就退化為指標了。

5、大部分編譯程式在編譯的時候就把sizeof計算過了是型別或是變數的長度,結果可以sizeof(x)結果可以用來定義陣列維數,strlen的結果要在執行的時候才能計算出來,是用來計算字串的長度,不是型別佔記憶體的大小。

1、sizeof 無法獲取動態分配的記憶體大小,即使用malloc/new動態的分配記憶體,無法使用sizeof獲取其大小。

2、vs2017中「 char* str = 「1234asd56」; 」 會報錯:"const char*"型別的值不能用於初始化"char*"型別的實體,但是vs2015及其以前的版本都不會報錯警告之類的。

int

display

(const std::string& str)

intmain

(int argc,

char

*ar**)

sizeof()在編譯階段進行,所以執行時並不會呼叫display函式,則不會列印出"hello world!"

深入理解c++中std::string的記憶體布局

占用位元組數求法

字串占用位元組數 ansi char szstr abc 占用位元組數求法 sizeof szstr char psz defgh 占用位元組數求法 strlen psz sizeof char unicode wchar t szwstr l abc 占用位元組數求法 sizeof szwstr ...

Oracle 漢字占用位元組數

在oracle中乙個字元特別是中文字元佔幾個位元組是與字符集有關的。比如gbk,漢字就會佔兩個位元組,英文1個 如果是utf 8,漢字一般佔3個位元組,英文還是1個。但是一般情況下,我們都認為是兩個位元組處理,因為oracle安裝時候預設我們都選擇gbk的編碼格式,但是我們在頁面做輸入字串長度的校驗...

List與陣列占用位元組數

想看一下list序列化後占用多少個 位元組,測試程式如下 public static void main string args throws ioexception system.out.println 元素數 list.size bytearrayoutputstream baos new by...