成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

為什么鳥(niǎo)哥說(shuō) int 再怎么隨機(jī)也申請(qǐng)不到奇數(shù)地址

klinson / 1015人閱讀

摘要:棧上各個(gè)變量申請(qǐng)的內(nèi)存,返回的地址是這段連續(xù)內(nèi)存的最小的地址。為什么用一個(gè)位的十六進(jìn)制來(lái)呢因?yàn)閭€(gè)字節(jié),一個(gè)字節(jié)有位,每位有兩個(gè)狀態(tài),那么就是,也就是。為什么用,純屬演示方便。結(jié)構(gòu)體里的字節(jié)對(duì)齊以成員中自身對(duì)齊值最大的那個(gè)值為標(biāo)準(zhǔn)。

原文:我的個(gè)人博客 https://mengkang.net/1046.html
初中級(jí) phper 有多久沒(méi)給自己充電了呢,安利一波我的直播 PHP 進(jìn)階之路
鳥(niǎo)哥微博

為什么要字節(jié)對(duì)齊

需要字節(jié)對(duì)齊的根本原因在于CPU訪問(wèn)數(shù)據(jù)的效率問(wèn)題。因?yàn)镃PU每次都是從以4字節(jié)(32位CPU)或是8字節(jié)(64位CPU)的整數(shù)倍的內(nèi)存地址中讀進(jìn)數(shù)據(jù)的。(更深入的原因,誰(shuí)告知下),如果不對(duì)齊的話,很有可能一個(gè)4字節(jié)int需要分兩次讀取。具體演示看下面的實(shí)驗(yàn)。

數(shù)據(jù)類型自身的對(duì)齊值

按各數(shù)據(jù)類型自身大小進(jìn)行對(duì)齊。變量的內(nèi)存地址正好位于它長(zhǎng)度的整數(shù)倍

實(shí)驗(yàn)
#include 

int main(int argc, char const *argv[])
{   
    char a = 1; // 0x7fff5fbff77f,sizeof(a):1
    int  b = 1; // 0x7fff5fbff778,sizeof(b):4
    int  c = 1; // 0x7fff5fbff774,sizeof(c):4
    char d = 1; // 0x7fff5fbff773,sizeof(e):1
    int  e = 1; // 0x7fff5fbff76c,sizeof(f):4
    
    printf("%p,sizeof(a):%lu
",&a,sizeof(a));
    printf("%p,sizeof(b):%lu
",&b,sizeof(b));
    printf("%p,sizeof(c):%lu
",&c,sizeof(c));
    printf("%p,sizeof(d):%lu
",&d,sizeof(d));
    printf("%p,sizeof(e):%lu
",&e,sizeof(e));

    return 0;
}
輔助以圖片說(shuō)明,該圖左側(cè)是上面代碼的內(nèi)存圖,灰色部分表示該程序未使用的內(nèi)存。右側(cè)是在上面代碼的基礎(chǔ)上在char a后面聲明了一個(gè)short f。

從上面的實(shí)驗(yàn)和圖上我們可以找出以下規(guī)律:

abcde 五個(gè)變量的內(nèi)存地址從大到下依次分配的;

如果你細(xì)看,會(huì)發(fā)現(xiàn)它們的內(nèi)存地址并不是緊密挨著的;

而且int 類型的變量的內(nèi)存地址都是偶數(shù)(這也就是為什么鳥(niǎo)哥微博中說(shuō)的不可能存在奇數(shù)的 int 變量的地址了);

再細(xì)看,發(fā)現(xiàn) int 變量的地址都是可以被4整除,所以在棧上各變量是按各數(shù)據(jù)類型自身大小進(jìn)行對(duì)齊的。

新增的short f 地址也并沒(méi)有緊挨著a,而是跟自身數(shù)據(jù)大小對(duì)齊,也就是偶數(shù)地址開(kāi)始申請(qǐng)。

棧上各個(gè)變量申請(qǐng)的內(nèi)存,返回的地址是這段連續(xù)內(nèi)存的最小的地址。

反過(guò)來(lái)想,如果不對(duì)齊,比如上例中的 a,b,c 三個(gè)變量的內(nèi)存地址緊挨著,而CPU每次只讀取8個(gè)字節(jié),也就是說(shuō)變量 c 還有最后一個(gè)字節(jié)沒(méi)有讀取進(jìn)來(lái)。訪問(wèn)數(shù)據(jù)效率就降低了。

棧上各個(gè)變量申請(qǐng)的內(nèi)存,返回的地址是這段連續(xù)內(nèi)存的最小的地址。這是怎么回事呢?

我們還是通過(guò)實(shí)驗(yàn)來(lái)驗(yàn)證下我上面畫的內(nèi)存圖,假如我有一個(gè)int變量,它的值占了滿了4個(gè)字節(jié),那么它的四個(gè)字節(jié)里是怎么存放數(shù)據(jù)的,我們用十六進(jìn)制來(lái)演示0x12345678

為什么用一個(gè)8位的十六進(jìn)制來(lái)呢?因?yàn)閕nt 4個(gè)字節(jié),一個(gè)字節(jié)有8位,每位有0/1兩個(gè)狀態(tài),那么就是2^8=256,也就是16^2。所以用了一個(gè)8位的16進(jìn)制數(shù)正好可以填滿一個(gè) int 的內(nèi)存。

為什么用12345678,純屬演示方便。

我先存了變量 b,然后以 char 指針 p 來(lái)依次訪問(wèn) b 的四個(gè)字節(jié)的使用情況。

#include 

int main(int argc, char const *argv[])
{
    char a = 1;             // 0x7fff5fbff777
    int  b = 0x12345678;    // 0x7fff5fbff770
    char c = 1;             // 0x7fff5fbff76f
    printf("%p
",&a);
    printf("%p
",&b);
    printf("%p
",&c);

    char *p = (char *)&b;
    
    printf("%x %x %x %x
", p[0],p[1],p[2],p[3]); // 78 56 34 12
    printf("%p %p %p %p
", &p[0],&p[1],&p[2],&p[3]); // 0x7fff5fbff770 0x7fff5fbff771 0x7fff5fbff772 0x7fff5fbff773
        
    return 0;
}

變量 b 0x12345678的最高位是0x12,最低位是0x78
針對(duì)實(shí)驗(yàn)結(jié)果我又畫了內(nèi)存圖,我們可以看到0x12存放在的內(nèi)存地址要比0x78的大。

這里呢就必須說(shuō)明下 大小端模式

小端法(Little-Endian)就是低位字節(jié)排放在內(nèi)存的低地址端即該值的起始地址,高位字節(jié)排放在內(nèi)存的高地址端。

大端法(Big-Endian)就是高位字節(jié)排放在內(nèi)存的低地址端即該值的起始地址,低位字節(jié)排放在內(nèi)存的高地址端。

所以,我當(dāng)前的環(huán)境是小端序的形式。

為什么會(huì)有大端小端之分?
這個(gè)就得問(wèn)硬件廠商了,都比較任性,所以歷史就這樣了。
結(jié)構(gòu)體里的字節(jié)對(duì)齊

以成員中自身對(duì)齊值最大的那個(gè)值為標(biāo)準(zhǔn)。

實(shí)驗(yàn)
int main(int argc, char const *argv[])
{
    struct str1{
        char a;
        short b;
        int c;
    };
    
    printf("sizeof(f):%lu
",sizeof(struct str1));
    
    struct str2{
        char a;
        int c;
        short b;
    };
    
    printf("sizeof(g):%lu
",sizeof(struct str2));
    
    struct str1 a;
    printf("a.a %p
",&a.a);
    printf("a.b %p
",&a.b);
    printf("a.c %p
",&a.c);
    
    struct str2 b;
    printf("b.a %p
",&b.a);
    printf("b.c %p
",&b.c);
    printf("b.b %p
",&b.b);

    
    return 0;
}

結(jié)果

sizeof(f):8
sizeof(g):12
a.a 0x7fff5fbff778
a.b 0x7fff5fbff77a
a.c 0x7fff5fbff77c
b.a 0x7fff5fbff768
b.c 0x7fff5fbff76c
b.b 0x7fff5fbff770
原理

灰色表填充用來(lái)對(duì)齊,保證最后結(jié)構(gòu)體大小是最長(zhǎng)的成員的大小的整數(shù)倍。

例外

實(shí)際工作中是否不按字節(jié)對(duì)齊的情況呢?有的,比如我們的 rpc 框架里面進(jìn)行數(shù)據(jù)傳輸?shù)臅r(shí)候,會(huì)選擇設(shè)置為緊湊型,這樣就可以輕松做到跨平臺(tái),跨語(yǔ)言了。
在網(wǎng)絡(luò)程序中采用#pragma pack(1),即變量緊縮,不但可以減少網(wǎng)絡(luò)流量,還可以兼容各種系統(tǒng),不會(huì)因?yàn)橄到y(tǒng)對(duì)齊方式不同而導(dǎo)致解包錯(cuò)誤。

實(shí)戰(zhàn)舉例 yar_header 中使用 #pragma pack(1) 和 attribute ((packed)) 的意義

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/26255.html

相關(guān)文章

  • 【C語(yǔ)言】超詳講解??指針是個(gè)什么針?(一次性搞定指針問(wèn)題)

    目錄 前言 一、 什么是指針? 引例 計(jì)算機(jī)是怎么對(duì)內(nèi)存單元編號(hào)的呢? 內(nèi)存空間的地址如何得到 想存地址怎么辦? ? 本質(zhì)目的不是為了存地址 ?二、指針和指針類型 為什么有不同類型的指針 1.指針的解引用 2.指針+-整數(shù) 三、野指針 造成野指針的原因 1.未主動(dòng)初始化指針 ?2.指針越界訪問(wèn) 3.指針指向的空間釋放 規(guī)避野指針 四、指針運(yùn)算 1.指針+-整數(shù) ?2.指針-指針 ?3.指針的關(guān)系運(yùn)...

    tigerZH 評(píng)論0 收藏0
  • C/C++

    摘要:另外棧內(nèi)存出了作用域就會(huì)自動(dòng)釋放掉,所以不需要手動(dòng)去回收的。,其中指針變量的聲明有如下三種形式其中第一種是被推薦的寫法。數(shù)據(jù)類型 C語(yǔ)言中的基本數(shù)據(jù)類型,對(duì)于它分為兩種: 1、signed 有符號(hào)的類型,也就是支持正負(fù)號(hào)的。 2、unsigned 無(wú)符號(hào)的類型,也就是沒(méi)有負(fù)號(hào),取值從0開(kāi)始。 有符號(hào)和無(wú)符號(hào)的數(shù)據(jù)類型有啥區(qū)別呢?其實(shí)就是取值范圍不一樣,下面看一張對(duì)照表: showImg(ht...

    microcosm1994 評(píng)論0 收藏0
  • 用React寫一個(gè)數(shù)字華容道,你需要知道的秘密

    摘要:還在上班很無(wú)聊數(shù)字華容道暢玩地址開(kāi)發(fā)源碼地址這個(gè)叫前言年末了。光隨機(jī)生成一個(gè)亂序數(shù)列是不夠的,還得保證這個(gè)數(shù)列的逆序數(shù)為偶數(shù),嗦嘎。所以,我們直接將交換的次數(shù),記為數(shù)列逆序數(shù)個(gè)數(shù),就達(dá)到了想要的效果。 還在上班?很無(wú)聊?數(shù)字華容道暢玩地址 開(kāi)發(fā)源碼地址 這個(gè)叫前言 年末了。哦,不,要過(guò)年了。以前只能一路站到公司的我,今早居然是坐著過(guò)來(lái)的。新的一年,總要學(xué)一個(gè)新東西來(lái)迎接新的未來(lái)吧,所以...

    Jason 評(píng)論0 收藏0
  • [零基礎(chǔ)學(xué)python]復(fù)習(xí)if語(yǔ)句

    摘要:在學(xué)習(xí)語(yǔ)句的時(shí)候,對(duì)編程的基礎(chǔ)知識(shí)了解的還不是很多,或許沒(méi)有做什么太復(fù)雜的東西??梢酝ㄟ^(guò)一個(gè)內(nèi)置函數(shù)來(lái)判斷一個(gè)條件的結(jié)果還是。有朋友需要看完整教程內(nèi)容,請(qǐng)點(diǎn)擊零基礎(chǔ)學(xué),這里會(huì)及時(shí)更新,并且有完整的目錄結(jié)構(gòu),更吸納了朋友們提出的意見(jiàn)和建議。 看官是否記得,在上一部分的時(shí)候,有一講專門介紹if語(yǔ)句的:從if開(kāi)始語(yǔ)句的征程。在學(xué)習(xí)if語(yǔ)句的時(shí)候,對(duì)python編程的基礎(chǔ)知識(shí)了解的還不是很多,...

    array_huang 評(píng)論0 收藏0
  • RecyclerView瀑布流優(yōu)化方案探討

    摘要:是規(guī)則的瀑布流。普通的尺寸會(huì)出現(xiàn)錯(cuò)位的問(wèn)題索引這個(gè)是右邊這個(gè)是左邊間距解決辦法,可以通過(guò)里的來(lái)判斷,這個(gè)方法不管你高度怎樣,他都是左右左右開(kāi)始排列的。 目錄介紹 01.規(guī)則瀑布流實(shí)現(xiàn)02.不規(guī)則瀑布流實(shí)現(xiàn)2.1 實(shí)現(xiàn)方式2.2 遇到問(wèn)題03.瀑布流上拉加載04.給瀑布流設(shè)置分割線05.自定義Manager崩潰06.如何避免刷新抖動(dòng)07.為何有時(shí)出現(xiàn)跳動(dòng)08.瀑布流圖片優(yōu)化09.onBi...

    zhaofeihao 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<