最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解C++ sizeof(下)

 更新時(shí)間:2020年08月15日 10:17:33   作者:Dabelv  
這篇文章主要介紹了C++ sizeof的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)c++,感興趣的朋友可以了解下

sizeof作用于基本數(shù)據(jù)類型,在特定的平臺(tái)和特定的編譯器中,結(jié)果是確定的,如果使用sizeof計(jì)算構(gòu)造類型:結(jié)構(gòu)體、聯(lián)合體和類的大小時(shí),情況稍微復(fù)雜一些。

1.sizeof計(jì)算結(jié)構(gòu)體

考察如下代碼:

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

sizeof(S1)結(jié)果是8,并不是想象中的sizeof(char)+sizeof(int)=5。這是因?yàn)榻Y(jié)構(gòu)體或類成員變量具有不同類型時(shí),需進(jìn)行成員變量的對(duì)齊?!队?jì)算機(jī)組成原理》一書(shū)中說(shuō)明,對(duì)齊的目的是減少訪存指令周期,提高CPU存儲(chǔ)速度。

1.1內(nèi)存對(duì)齊原則

(1)結(jié)構(gòu)體變量的首地址能夠被其最寬基本成員類型大小所整除;

(2)結(jié)構(gòu)體每個(gè)成員相對(duì)于結(jié)構(gòu)體首地址的偏移量都是成員大小的整數(shù)倍,如有需要編譯器會(huì)在成員之間加上填充字節(jié);

(3)結(jié)構(gòu)體的總大小為結(jié)構(gòu)體最寬基本成員類型大小的整數(shù)倍,如有需要編譯器會(huì)在最末一個(gè)成員之后加上填充字節(jié)。

有了以上三個(gè)內(nèi)存對(duì)齊的原則,就可以輕松應(yīng)對(duì)嵌套結(jié)構(gòu)體類型的內(nèi)存對(duì)齊。如下:

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

在尋找S2的最寬基本數(shù)據(jù)類型時(shí),包括其嵌套的結(jié)構(gòu)體中的成員,從S1中尋找出最寬結(jié)構(gòu)體數(shù)據(jù)類型是int,因此S2的最寬數(shù)據(jù)類型是int。S1 s在結(jié)構(gòu)體S2中的對(duì)齊也遵守前三個(gè)準(zhǔn)則,因此sizeof(S2)=sizeof(char)+pad(3)+sizeof(S1)+1+pad(3)=1+3+8+1+3=16字節(jié),其中pad(3)表示填充3個(gè)字節(jié)。

結(jié)構(gòu)體某個(gè)成員相對(duì)于結(jié)構(gòu)體首地址的偏移量可以通過(guò)宏offsetof()來(lái)獲得,這個(gè)宏也在stddef.h中定義,如下:

#define offsetof(s,m) (size_t)&(((s *)0)->m)

例如獲得S1中的偏移量,方法為

size_t pos = offsetof(S1, i); //pos等于4

1.2修改對(duì)齊方式

1.2.1#pragma pack

#pragma pack(n)中n為字節(jié)對(duì)齊數(shù),其取值為1、2、4、8、16,默認(rèn)是8。結(jié)構(gòu)體對(duì)齊時(shí),

(1)成員的偏移量為成員本身大小和n二者最小值的整數(shù)倍;
(2)結(jié)構(gòu)體最終大小是結(jié)構(gòu)體中最寬基本類型成員大小和n二者中的最小值的整數(shù)倍。

考察如下代碼:

#pragma pack(push) //將當(dāng)前pack設(shè)置壓棧保存
#pragma pack(2) //必須在結(jié)構(gòu)體定義之前使用
struct S1
{
char c;
int i;
};
struct S2
{
char c1;
S1 s;
char c2
};
#pragma pack(pop) // 恢復(fù)先前的pack設(shè)置

//或者
#pragma pack(2)
...
#pragma pack()

因此,sizeof(S2)=sizeof(char)+pad(1)+sizeof(S1)+1+pad(1)=1+1+6+1=10字節(jié)。

注意,#pragma pack不能指定變量的存儲(chǔ)地址,變量的首地址默認(rèn)為最大基本成員類型大小的整數(shù)倍。

1.2.2__declspec(align(#))

VC++支持__declspec(align(#)),在GNU C++并不支持。#的取值為1~8192,為2的冪。使用示例如下:

__declspec(align(256)) struct TestSize
{
char a;
int i;
};
cout<<sizeof(TestSize)<<endl; //輸出256

__declspec(align(#))要求#為2的整數(shù)次冪,作用主要有兩個(gè)方面:
(1)使結(jié)構(gòu)體或類成員按#pragma pack確定內(nèi)存布局之后,在末尾填充內(nèi)存使得整個(gè)對(duì)象的大小至少是#的整數(shù)倍。
(2)作用于變量時(shí),強(qiáng)制要求編譯器將變量放置在地址是#整數(shù)倍的內(nèi)存位置上。這點(diǎn)在調(diào)用原生API等要求嚴(yán)格對(duì)齊的方法時(shí)十分重要。

1.3空結(jié)構(gòu)體

C/C++中不允許長(zhǎng)度為0的數(shù)據(jù)類型存在。對(duì)于“空結(jié)構(gòu)體”(不含數(shù)據(jù)成員)的大小不為0,而是1?!翱战Y(jié)構(gòu)體”變量也得被存儲(chǔ),這樣編譯器也就只能為其分配一個(gè)字節(jié)的空間用于占位了。如下:

struct S3 { };
sizeof(S3); // 結(jié)果為1

1.4位域結(jié)構(gòu)體

有些信息在存儲(chǔ)時(shí),并不需要占用一個(gè)完整的字節(jié), 而只需占一個(gè)或多個(gè)二進(jìn)制位。例如在存放一個(gè)開(kāi)關(guān)量時(shí),只有0和1 兩種狀態(tài), 用一位即可表示。為了節(jié)省存儲(chǔ)空間,并使處理簡(jiǎn)便,C語(yǔ)言又提供了一種數(shù)據(jù)結(jié)構(gòu),稱為”位域”或”位段”。包含位域變量的結(jié)構(gòu)體叫作位域結(jié)構(gòu)體。位域結(jié)構(gòu)體的定義形式:

struct 位域結(jié)構(gòu)體名
{ 
類型說(shuō)明符 位域名:位域長(zhǎng)度;
...
};

注意,位域長(zhǎng)度不應(yīng)該大于該類型說(shuō)明符對(duì)應(yīng)的數(shù)據(jù)類型的位長(zhǎng)度。
使用位域的主要目的是壓縮存儲(chǔ),其大致規(guī)則為:

(1)如果相鄰位域字段的類型相同,且其位寬之和小于類型的sizeof大小,則后面的字段將緊鄰前一個(gè)字段存儲(chǔ),直到不能容納為止;
(2)如果相鄰位域字段的類型相同,但其位寬之和大于類型的sizeof大小,則后面的字段將從新的存儲(chǔ)單元開(kāi)始,其偏移量為其類型大小的整數(shù)倍;
(3)如果相鄰位域字段的類型不同,則各編譯器的具體實(shí)現(xiàn)有差異,VC++采取不壓縮方式,GNU C++采取壓縮方式;
(4)如果位域字段之間穿插著非位域字段,則不進(jìn)行壓縮;
(5)整個(gè)結(jié)構(gòu)體的總大小為最寬基本類型成員大小的整數(shù)倍;
(6)位域可以無(wú)位域名,這時(shí)它只用作填充或調(diào)整位置,不能使用。例如:

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

關(guān)于位域結(jié)構(gòu)體的sizeof大小,考察如下代碼:

#include <iostream>
using namespace std;

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;
};

int main()
{
cout<<sizeof(BFS1)<<endl;
cout<<sizeof(BFS2)<<endl;
cout<<sizeof(BFS3)<<endl;
}

運(yùn)行上面的程序,VC++和GNU C++輸出結(jié)果如下:

//VC++輸出結(jié)果
2
12
3

//GNU C++輸出結(jié)果
2
4
3

考察以上代碼,得出:

(1)sizeof(BFS1)==2。當(dāng)相鄰位域類型不同,在VC++中sizeof(BFS2)=1+pad(3)+4+1+pad(3)=12,采用不壓縮方式,位域變量i的偏移量需要是4的倍數(shù),并且位域結(jié)構(gòu)體BFS2的總大小必須是sizeof(int)的整數(shù)倍。在GNU C++中為sizeof(BFS2)=4,相鄰的位域字段的類型不同時(shí),采取了壓縮存儲(chǔ),位域變量i緊隨位域變量f1的剩余位進(jìn)行存儲(chǔ),位域變量f2同樣是緊隨位域變量i的剩余位進(jìn)行存儲(chǔ),并且位域結(jié)構(gòu)體BFS2的總大小必須是sizeof(int)的整數(shù)倍,所以最終結(jié)果sizeof(BFS2)=1+pad(3)=4。

(2)sizeof(BFS3)==3,當(dāng)非位域字段穿插在其中,不會(huì)產(chǎn)生壓縮,在VC++和GNU C++中得到的大小均為3,如果壓縮存儲(chǔ),則sizeof(BFS3)==2。

2.sizeof計(jì)算共用體

結(jié)構(gòu)體在內(nèi)存組織上是順序式的,共用體則是重疊式,各成員共享一段內(nèi)存,所以整個(gè)共用體的sizeof也就是每個(gè)成員sizeof的最大值。結(jié)構(gòu)體的成員也可以是構(gòu)造類型,這里,構(gòu)造類型成員是被作為整體考慮的。所以,下面例子中,假設(shè)sizeof(s)的值大于sizeof(i)和sizeof(c),那么sizeof(U)等于sizeof(s)。

union U
{
int i;
char c;
S1 s;
};

3.sizeof計(jì)算類

類是C++中常用的自定義構(gòu)造類型,有數(shù)據(jù)成員和成員函數(shù)組成,進(jìn)行sizeof計(jì)算時(shí),和結(jié)構(gòu)體并沒(méi)有太大的區(qū)別??疾烊缦麓a:

#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;
}

注意一點(diǎn),C++中類同結(jié)構(gòu)體沒(méi)有本質(zhì)的區(qū)別,結(jié)構(gòu)體同樣可以包含成員函數(shù),構(gòu)造函數(shù),析構(gòu)函數(shù),虛函數(shù)和繼承,但一般不這么使用,沿用了C的結(jié)構(gòu)體使用習(xí)慣。類與結(jié)構(gòu)體唯一的區(qū)別就是結(jié)構(gòu)體的成員的默認(rèn)權(quán)限是public,而類是private。

基于以上這點(diǎn),再考察從程序的輸出結(jié)果,得出如下結(jié)論:

(1)類同結(jié)構(gòu)體一樣,C++中不允許長(zhǎng)度為0的數(shù)據(jù)類型存在,雖然類無(wú)任何成員,但該類的對(duì)象仍然占用1個(gè)字節(jié)。
(2)類的成員函數(shù)并不影響類對(duì)象占用的空間,類對(duì)象的大小是由它數(shù)據(jù)成員決定的。
(3)類和結(jié)構(gòu)體一樣,同樣需要對(duì)齊,具體對(duì)齊的規(guī)則見(jiàn)上文結(jié)構(gòu)體的內(nèi)存對(duì)齊。
(4)類如果包含虛函數(shù),編譯器會(huì)在類對(duì)象中插入一個(gè)指向虛函數(shù)表的指針,以幫助實(shí)現(xiàn)虛函數(shù)的動(dòng)態(tài)調(diào)用。

所以,該類的對(duì)象的大小至少比不包含虛函數(shù)時(shí)多4個(gè)字節(jié)。如果考慮內(nèi)存對(duì)齊,可能還要多些。如果使用數(shù)據(jù)成員之間的對(duì)齊,當(dāng)類對(duì)象至少包含一個(gè)數(shù)據(jù)成員,且擁有虛函數(shù),那么該對(duì)象的大小至少是8B,讀者可自行推導(dǎo)。

以上就是詳解C++ sizeof(下)的詳細(xì)內(nèi)容,更多關(guān)于C++ sizeof的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C語(yǔ)言實(shí)現(xiàn)的PNPoly算法代碼例子

    C語(yǔ)言實(shí)現(xiàn)的PNPoly算法代碼例子

    這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)的PNPoly算法代碼例子,PNPoly算法j是判斷一個(gè)坐標(biāo)點(diǎn)是否在不規(guī)則多邊形內(nèi)部的算法,需要的朋友可以參考下
    2014-07-07
  • C++文件上傳、下載工具

    C++文件上傳、下載工具

    這篇文章主要為大家詳細(xì)介紹了C++文件上傳、下載工具的相關(guān)資料,感興趣的小伙伴們可以參考一下
    2016-05-05
  • c++類構(gòu)造函數(shù)詳解

    c++類構(gòu)造函數(shù)詳解

    這篇文章主要介紹了c++類構(gòu)造函數(shù)示例,需要的朋友可以參考下
    2014-05-05
  • C++簡(jiǎn)單實(shí)現(xiàn)與分析二叉搜索樹(shù)流程

    C++簡(jiǎn)單實(shí)現(xiàn)與分析二叉搜索樹(shù)流程

    二叉搜索樹(shù)作為一個(gè)經(jīng)典的數(shù)據(jù)結(jié)構(gòu),具有鏈表的快速插入與刪除的特點(diǎn),同時(shí)查詢效率也很優(yōu)秀,所以應(yīng)用十分廣泛。本文將詳細(xì)講講二叉搜索樹(shù)的C++實(shí)現(xiàn),需要的可以參考一下
    2022-08-08
  • Qt5 串口類QSerialPort的實(shí)現(xiàn)

    Qt5 串口類QSerialPort的實(shí)現(xiàn)

    在Qt5以上提供了QtSerialPort模塊,方便編程人員快速的開(kāi)發(fā)應(yīng)用串口的應(yīng)用程序。本文主要介紹了Qt5 串口類QSerialPort的實(shí)現(xiàn),,感興趣的可以了解一下
    2022-05-05
  • Visual C++程序設(shè)計(jì)中Windows GDI貼圖閃爍的解決方法

    Visual C++程序設(shè)計(jì)中Windows GDI貼圖閃爍的解決方法

    這篇文章主要介紹了Visual C++程序設(shè)計(jì)中Windows GDI貼圖閃爍的解決方法,分析了GDI貼圖閃爍的常見(jiàn)原因及其具體解決方法,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-01-01
  • C語(yǔ)言 超詳細(xì)介紹與實(shí)現(xiàn)線性表中的帶頭雙向循環(huán)鏈表

    C語(yǔ)言 超詳細(xì)介紹與實(shí)現(xiàn)線性表中的帶頭雙向循環(huán)鏈表

    帶頭雙向循環(huán)鏈表:結(jié)構(gòu)最復(fù)雜,一般用在單獨(dú)存儲(chǔ)數(shù)據(jù)。實(shí)際中使用的鏈表數(shù)據(jù)結(jié)構(gòu),都是帶頭雙向循環(huán)鏈表。另外這個(gè)結(jié)構(gòu)雖然結(jié)構(gòu)復(fù)雜,但是使用代碼實(shí)現(xiàn)以后會(huì)發(fā)現(xiàn)結(jié)構(gòu)會(huì)帶來(lái)很多優(yōu)勢(shì),實(shí)現(xiàn)反而簡(jiǎn)單
    2022-03-03
  • C++ tuple元組的基本用法(總結(jié))

    C++ tuple元組的基本用法(總結(jié))

    這篇文章主要介紹了C++ tuple元組的基本用法(總結(jié)),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • c++中c_str()的用法示例

    c++中c_str()的用法示例

    這篇文章主要介紹了c++中c_str()的用法示例,幫助大家更好的理解和學(xué)習(xí)C++,感興趣的朋友可以了解下
    2020-09-09
  • C語(yǔ)言中程序環(huán)境和預(yù)處理的詳細(xì)圖文講解

    C語(yǔ)言中程序環(huán)境和預(yù)處理的詳細(xì)圖文講解

    這篇文章主要給大家介紹了關(guān)于C語(yǔ)言中程序環(huán)境和預(yù)處理的相關(guān)資料,我們寫(xiě)的C語(yǔ)言代碼,從運(yùn)行,到在屏幕上生成結(jié)果,經(jīng)歷了比較復(fù)雜的過(guò)程,需要的朋友可以參考下
    2023-02-02

最新評(píng)論

瑞安市| 上栗县| 东海县| 华容县| 绥德县| 蓝田县| 武冈市| 出国| 安达市| 汶上县| 连州市| 通州区| 西乌珠穆沁旗| 西宁市| 城市| 贵港市| 安顺市| 红安县| 兴隆县| 金昌市| 顺义区| 东乌珠穆沁旗| 隆子县| 化隆| 定远县| 溧阳市| 万宁市| 葵青区| 拉孜县| 民权县| 兴隆县| 郁南县| 汉沽区| 茂名市| 富裕县| 曲麻莱县| 河池市| 襄汾县| 兴安县| 石狮市| 资源县|