亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C語(yǔ)言熱門(mén)考點(diǎn)結(jié)構(gòu)體與內(nèi)存對(duì)齊詳解

 更新時(shí)間:2021年10月22日 15:54:41   作者:高郵吳少  
在掌握基本的結(jié)構(gòu)體使用后,我們?cè)诿嬖嚭痛笮捅荣愔谐3?huì)遇到一個(gè)熱門(mén)考點(diǎn):結(jié)構(gòu)體內(nèi)存對(duì)齊,也就是計(jì)算結(jié)構(gòu)體大小。接下來(lái)請(qǐng)跟著筆者一起來(lái)學(xué)習(xí)這塊知識(shí)點(diǎn)吧

一、引例

到底什么是結(jié)構(gòu)體內(nèi)存對(duì)齊,我們用一段代碼來(lái)介紹一下

struct S1
{
	char c1;//1字節(jié)
	int a;//4字節(jié)
	char c2;//1字節(jié)
};
int main()
{
	printf("%d\n", sizeof(struct S1));
	//這里打印12
}

先來(lái)解釋S1,結(jié)構(gòu)體S1中有2個(gè)char類型,1個(gè)int類型。那按道理應(yīng)該是占2*1+4=6個(gè)字節(jié)啊,為什么打印的是12呢?到這里,我們必須要來(lái)了解一下結(jié)構(gòu)體內(nèi)存對(duì)齊的規(guī)則:

1.結(jié)構(gòu)體的第一個(gè)成員永遠(yuǎn)放在結(jié)構(gòu)體起始位置偏移量為0的位置

對(duì)于偏移量你可以這樣理解:數(shù)組下標(biāo)為0的相對(duì)它自己偏移量為0,下標(biāo)為1的相對(duì)下標(biāo)為0的偏移量為1…
舉例說(shuō)明:

在這里插入圖片描述

S1第一個(gè)成員是c1,它會(huì)被放在結(jié)構(gòu)體起始位置偏移量為0的位置,如下圖紅色部分

在這里插入圖片描述

2.從第二個(gè)成員開(kāi)始,總是放在偏移量為一個(gè)對(duì)齊數(shù)的整數(shù)處,對(duì)齊數(shù)=編譯器默認(rèn)的對(duì)齊數(shù)和變量自身大小的較小值

對(duì)齊數(shù)=min(編譯器默認(rèn)的對(duì)齊數(shù),變量自身大小)
Linux-沒(méi)有對(duì)齊數(shù),VS下對(duì)齊數(shù)默認(rèn)為8

我們?nèi)砸許1這個(gè)結(jié)構(gòu)體進(jìn)行舉例,結(jié)構(gòu)體第二個(gè)成員是int類型的a,占4個(gè)字節(jié),筆者VS環(huán)境下默認(rèn)對(duì)齊數(shù)是8,取兩者較小值是4,那a應(yīng)該放到偏移量為4的倍數(shù)上

在這里插入圖片描述

放到4的倍數(shù)上也就說(shuō)可以放在偏移量為4這里,偏移量為1,2,3的這3個(gè)空間就白白被浪費(fèi)了。而a是int型占4個(gè)字節(jié),所以會(huì)一直占用到偏移量為7的位置。

接下來(lái)是結(jié)構(gòu)體的第三個(gè)成員,char類型的c2,c2占1個(gè)字節(jié),VS環(huán)境下默認(rèn)對(duì)齊數(shù)是8,取較小值為1,也就是說(shuō)只要是1的倍數(shù)的偏移量都可以放,我們緊接著放在a后面,也就是偏移量8的位置

在這里插入圖片描述

那到這里結(jié)構(gòu)體3個(gè)成員都用完了啊,只有8個(gè)啊,為什么打印是12呢?這里就要涉及結(jié)構(gòu)體內(nèi)存對(duì)齊的第3個(gè)規(guī)則

3.結(jié)構(gòu)體的總大小必須是各個(gè)成員的對(duì)齊數(shù)中最大的那個(gè)對(duì)齊數(shù)的整數(shù)倍

我們由前面講解知道結(jié)構(gòu)體三個(gè)成員c1,a,c2對(duì)齊數(shù)分別為1,4,1這三個(gè)中最大對(duì)齊數(shù)是4,總大小要為4的整數(shù)倍,那這時(shí)候肯定有小伙伴會(huì)問(wèn):我們現(xiàn)在不是對(duì)齊到8了嘛,8不是4的倍數(shù)嗎?注意!這里說(shuō)的是空間總大小,而8是所謂的偏移量,偏移量是從0開(kāi)始算的,到8已經(jīng)有9個(gè)空間了,所以我們這里空間要到12,也就是偏移量到11

在這里插入圖片描述

(后面加上的三個(gè)空間用不到,但是由于規(guī)定還是算在結(jié)構(gòu)體總空間內(nèi))

二、小試牛刀

我們?cè)賮?lái)看一道類似的題目

代碼如下(示例):

struct S2
{
	char c1;//1字節(jié)
	char c2;//1字節(jié)
	int a;//4字節(jié)
};
int main()
{
	printf("%d\n", sizeof(struct S2));
	//這里打印8
}

首先第一個(gè)結(jié)構(gòu)體成員是char類型的c1,由規(guī)則1,它會(huì)直接被放在偏移量為0的位置
(圖示灰色部分)

在這里插入圖片描述

第二個(gè)成員是char類型的c2,占1字節(jié),VS下默認(rèn)對(duì)齊數(shù)是8,取較小值是1,只要放在偏移量為1的倍數(shù)上即可(任意位置),緊跟著0,放在偏移量為1處(圖示紅色部分)

在這里插入圖片描述

最后一個(gè)成員int類型的a,占4個(gè)字節(jié),VS環(huán)境下默認(rèn)對(duì)齊數(shù)是8,取較小者4,放在偏移量為4的整數(shù)倍處,也就是4這里,然后由于int占4個(gè)字節(jié)所以一直占用到偏移量7處

在這里插入圖片描述

再來(lái)看看規(guī)則3,結(jié)構(gòu)體的總大小必須是各個(gè)成員的對(duì)齊數(shù)中最大的那個(gè)對(duì)齊數(shù)的整數(shù)倍,也就是4的倍數(shù),我們現(xiàn)在正好是占8個(gè)空間,8正好是4的倍數(shù),所以就不用再往下浪費(fèi)空間了,打印出8

三、嵌套結(jié)構(gòu)體的特殊情況

代碼如下(示例):

struct S3
{
	double d;//double占8字節(jié),默認(rèn)對(duì)齊數(shù)8,取較小值,對(duì)齊數(shù)8
	char c;//對(duì)齊數(shù)1
	int i;//對(duì)齊數(shù)4
};
struct S4
{
	char c1;
	struct S3 s3;
	double d;
};
int main()
{
	printf("%d\n", sizeof(struct S4));
}

關(guān)于結(jié)構(gòu)體S3我們可以采用和前面S1、S2一樣的方法計(jì)算出來(lái)是占16個(gè)字節(jié)空間,我們這里重點(diǎn)討論S4,對(duì)S3有興趣的小伙伴可自行求解。

S4中的第一個(gè)成員c1,按規(guī)則1直接放在偏移量為0處,第二個(gè)成員s3怎么辦呢?這里涉及結(jié)構(gòu)體內(nèi)存對(duì)齊的第四個(gè)規(guī)則:

如果嵌套了結(jié)構(gòu)體的情況,嵌套的結(jié)構(gòu)體對(duì)齊到自己的最大對(duì)齊數(shù)的整數(shù)倍數(shù)處,結(jié)構(gòu)體的整體大小就是所有最大對(duì)齊數(shù)(含嵌套結(jié)構(gòu)體的對(duì)齊數(shù))的整數(shù)倍

s3這個(gè)結(jié)構(gòu)體三個(gè)成員最大對(duì)齊數(shù)是8,也就是要對(duì)齊到偏移量為8的倍數(shù)處,然后s3是占16個(gè)字節(jié),所以一直占到偏移量23處(s3結(jié)構(gòu)體對(duì)齊數(shù)是本身s3結(jié)構(gòu)體三個(gè)成員中最大對(duì)齊數(shù))

ps:在VS環(huán)境中,嵌套結(jié)構(gòu)體的最大對(duì)齊數(shù)超過(guò)8,仍然用8做最大對(duì)齊數(shù)(比默認(rèn)對(duì)齊數(shù)大了,取較小值就取默認(rèn)對(duì)齊數(shù)了)

在這里插入圖片描述

S4最后一個(gè)成員double類型的d占8字節(jié),默認(rèn)對(duì)齊數(shù)8,對(duì)齊數(shù)取8,然后放在偏移量為對(duì)齊數(shù)的整數(shù)倍處,正好往下放在24處,本身占8字節(jié)所以占到31

在這里插入圖片描述

偏移量0-31共占32字節(jié),S4中的成員c1,s3,d對(duì)齊數(shù)分別為1,8,8所以最大對(duì)齊數(shù)是8,32恰是8的倍數(shù),所以這里不用再浪費(fèi)空間來(lái)滿足 “結(jié)構(gòu)體的總大小必須是各個(gè)成員的對(duì)齊數(shù)中最大的那個(gè)對(duì)齊數(shù)的整數(shù)倍”這個(gè)規(guī)則,結(jié)構(gòu)體總大小就是32

四、關(guān)于為什么存在內(nèi)存對(duì)齊

1.平臺(tái)原因(移植原因):

不是所有的硬件平臺(tái)都能訪問(wèn)任意地址上的任意數(shù)據(jù)的;某些硬件平臺(tái)只能在某些地址處取某些特定的類型的數(shù)據(jù),否則拋出硬件異常

2.性能原因:

數(shù)據(jù)結(jié)構(gòu)(尤其是棧),應(yīng)盡可能地在自然邊界上對(duì)齊。原因在于,為了訪問(wèn)未對(duì)齊的內(nèi)存,處理器需要作兩次內(nèi)存訪問(wèn);而對(duì)齊的內(nèi)存訪問(wèn)僅僅需要1次
總體來(lái)說(shuō):結(jié)構(gòu)體的內(nèi)存對(duì)齊是用空間換時(shí)間

總結(jié)

本文介紹了結(jié)構(gòu)體內(nèi)存對(duì)齊的四大規(guī)則,并舉例說(shuō)明了如何進(jìn)行方法的操作,對(duì)于其中特殊的嵌套結(jié)構(gòu)體內(nèi)存對(duì)齊也進(jìn)行了相應(yīng)講解,希望讀者在學(xué)習(xí)完本文后能對(duì)結(jié)構(gòu)體內(nèi)存對(duì)齊有一個(gè)系統(tǒng)的認(rèn)識(shí)。祝讀者學(xué)業(yè)有成!

更多關(guān)于C語(yǔ)言結(jié)構(gòu)體與內(nèi)存對(duì)齊的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C++利用libcurl獲取下載文件名稱及大小

    C++利用libcurl獲取下載文件名稱及大小

    這篇文章主要為大家詳細(xì)介紹了C++如何利用libcurl獲取下載文件名稱及大小的功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2023-03-03
  • C++基礎(chǔ)入門(mén)教程(八):函數(shù)指針

    C++基礎(chǔ)入門(mén)教程(八):函數(shù)指針

    這篇文章主要介紹了C++基礎(chǔ)入門(mén)教程(八):函數(shù)指針,本文講解了函數(shù)原型和函數(shù)定義、const限定符與指針、函數(shù)的指針參數(shù)、為什么要使用指針參數(shù)等內(nèi)容,需要的朋友可以參考下
    2014-11-11
  • C語(yǔ)言實(shí)現(xiàn)制作通訊錄(新手推薦)

    C語(yǔ)言實(shí)現(xiàn)制作通訊錄(新手推薦)

    本文推薦給C語(yǔ)言學(xué)習(xí)到結(jié)構(gòu)體的新手們,供其練習(xí)。這篇文章主要是利用C語(yǔ)言制作一個(gè)簡(jiǎn)單的通訊錄功能,感興趣的小伙伴可以跟隨小編一起了解一下
    2022-09-09
  • C語(yǔ)言線性表順序表示及實(shí)現(xiàn)

    C語(yǔ)言線性表順序表示及實(shí)現(xiàn)

    這篇文章主要介紹了C語(yǔ)言線性表順序表示及實(shí)現(xiàn),線性表是最常用且最簡(jiǎn)單的一種數(shù)據(jù)結(jié)構(gòu)。簡(jiǎn)而言之,一個(gè)線性表是n個(gè)數(shù)據(jù)元素的有限序列
    2022-07-07
  • C++?opencv圖像處理使用cvtColor實(shí)現(xiàn)顏色轉(zhuǎn)換

    C++?opencv圖像處理使用cvtColor實(shí)現(xiàn)顏色轉(zhuǎn)換

    這篇文章主要為大家介紹了C++?opencv圖像處理cvtColor實(shí)現(xiàn)顏色轉(zhuǎn)換的實(shí)現(xiàn)示例代碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • C++命名空間 namespace詳解

    C++命名空間 namespace詳解

    定義命名空間,使用namespace關(guān)鍵字,后面跟命名空間的名字,然后接一對(duì)花括號(hào){ } 即可,{ }中即為命名空間的成員,這篇文章主要介紹了C++命名空間 namespace,需要的朋友可以參考下
    2023-04-04
  • C語(yǔ)言中各類指針的用法(小結(jié))

    C語(yǔ)言中各類指針的用法(小結(jié))

    這篇文章主要介紹了C語(yǔ)言中各類指針的用法(小結(jié)),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • 用C語(yǔ)言實(shí)現(xiàn)三子棋

    用C語(yǔ)言實(shí)現(xiàn)三子棋

    這篇文章主要為大家詳細(xì)介紹了用C語(yǔ)言實(shí)現(xiàn)三子棋,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • 基于Linux系統(tǒng)調(diào)用--getrlimit()與setrlimit()函數(shù)的方法

    基于Linux系統(tǒng)調(diào)用--getrlimit()與setrlimit()函數(shù)的方法

    本篇文章是對(duì)在Linux系統(tǒng)中調(diào)用getrlimit()與setrlimit()函數(shù)的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C++11新特性之右值引用與完美轉(zhuǎn)發(fā)詳解

    C++11新特性之右值引用與完美轉(zhuǎn)發(fā)詳解

    C++11標(biāo)準(zhǔn)為C++引入右值引用語(yǔ)法的同時(shí),還解決了一個(gè)短板,即使用簡(jiǎn)單的方式即可在函數(shù)模板中實(shí)現(xiàn)參數(shù)的完美轉(zhuǎn)發(fā)。本文就來(lái)講講二者的應(yīng)用,需要的可以參考一下
    2022-09-09

最新評(píng)論