日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人工智能 > pytorch >内容正文

pytorch

【C语言进阶深度学习记录】二十 结构体大小计算与结构体内存布局的详细方法

發布時間:2023/12/10 pytorch 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【C语言进阶深度学习记录】二十 结构体大小计算与结构体内存布局的详细方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
  • 結構體大小的計算往往是面試筆試常考的知識。對于簡單的結構體,可以一眼看出來,對于復雜的結構體,該如何計算結構體占用內存的大小呢?
  • 本文學習所使用的編譯器是gcc 4.4.5 使用其他編譯器或者使用Windows 上的編譯器有可能不太一樣。

文章目錄

    • 1 什么是內存對齊?
    • 2 struct占用的內存大小如何計算
      • 2.1 struct結構體大小計算案例分析-結構體中沒有結構體
      • 2.2 struct結構體大小計算案例分析-結構體中有一個結構體成員
    • 3 總結

1 什么是內存對齊?

先來加單的說一下為什么需要內存對齊:

  • CPU對內存的讀取不是連續的,而是分成塊讀取的,塊的大小只能是1,2,4,8,16…字節
  • 當讀取的數據未對齊,則需要兩次總線周期來訪問內存才能將整個數據讀完,這樣會降低CPU性能
  • 某些硬件平臺只能從規定的相對地址處讀取特定類型的數據,否則產生硬件異常
  • 什么是內存對齊?

    • 不同類型的數據在內存中按照一定的規則排列
    • 但是不一定是順序的一個接一個的排列

    例如下圖中的兩個結構體的大小是不一樣的,因為它們的內存布局是不一樣的:

    它們的內存布局如下圖:

    拓展: #pragma pack 用于指定內存的對齊方式。用于修改編譯器的默認對齊方式
    一般來講,在Linux系統中,編譯器的默認對我方式是4字節對齊。下圖中的代碼,可以將對齊方式修改為1字節對齊:

    2 struct占用的內存大小如何計算

    對于不同的內存對齊方式,上面的結構體在內存中的布局是不一樣的,那么我們如何來計算不同的對齊方式在內存中的布局是什么樣的呢?

    需要根據以下三點:

  • 第一個struct成員永遠起始于 0偏移處

  • 每個成員按其類型大小和pack參數中較小的一個 進行對齊

    2.1 偏移地址必須能被對齊參數整除
    2.2 如果一個結構體中有一個變量也是結構體,那么這個內部的結構體成員的對齊大小就按照其內部最大的數據成員作為其大小來計算。(這里有點繞,看最后的一個例子就會明白)

  • 結構體總長度,必須為所有對齊參數的整數倍

    • 只需要按照上述三點計算方法,就可以計算出所有結構體的大小以及內存布局的樣式

    2.1 struct結構體大小計算案例分析-結構體中沒有結構體

    如下面的代碼:

    • 24-3.c
    #include <stdio.h>#pragma pack(2) struct Test1 {char c1;short s;char c2;int i; }; #pragma pack()#pragma pack(4) struct Test2 {char c1;char c2;short s;int i; }; #pragma pack()int main() {printf("sizeof(Test1) = %d\n", sizeof(struct Test1));printf("sizeof(Test2) = %d\n", sizeof(struct Test2));return 0; }
    • 編譯運行結果為:

    sizeof(Test1) = 10
    sizeof(Test2) = 8

    • 結果分析1–Test1:

    對于結構體Test1,2字節對齊,按照上述三個計算條件有:

    struct Test1 { //對齊方式 大小 起始地址 占用的內存地址位置 char c1; 2 大于 1 0 0 short s; 2 等于 2 2(被對齊參數2整除) 2~3 char c2; 2 大于 1(對齊參數) 4 4 int i; 2(對齊參數) 小于 4 6(被對齊參數2整除) 6~9 };
  • Test1的對齊方式是2字節。
  • 然后根據:

  • 每個成員按其類型大小和pack參數中較小的一個 進行對齊。比如上面的起始地址計算那里,都是被對齊參數2整除,這個2是類型大小和pack參數中較小的一個

    2.1 偏移地址必須能被對齊參數整除

  • 這一條規則計算每個成員的起始地址。如上面的計算。

  • 最后再看總體大小是否是對齊參數的整數倍。上面Test1 大小是10,是對齊參數2的整數倍
    • 結果分析2–Test2

    對于結構體Test2,4字節對齊,按照上述三個計算條件有:

    struct Test2 { //對齊方式 大小 起始地址 占用的內存地址位置 char c1; 4 大于 1(對齊參數) 0 0 char c2; 4 大于 1(對齊參數) 1(被對齊參數1整除) 1 short s; 4 大于 2(對齊參數) 2(被對齊參數2整除) 2~3 int i; 4 等于 4(對齊參數) 4(被對齊參數4整除) 5~7 };
  • Test2 的對齊方式是4字節對齊
  • 然后再根據:

  • 每個成員按其類型大小和pack參數中較小的一個 進行對齊。比如上面的起始地址計算那里,對齊參數分別為1,1,2,4

    2.1 偏移地址必須能被對齊參數整除

  • 這一條規則計算每個成員的起始地址。如上面的計算。

  • 最后再看總體大小是否是對齊參數的整數倍。上面Test2 大小是8,是對齊參數4的整數倍
  • 經過上面的兩個結構體大小的計算,可以很容易的畫出其內存圖

    2.2 struct結構體大小計算案例分析-結構體中有一個結構體成員

    再看一個復雜的結構體大小的計算

    • 代碼 24-4.c
    #include <stdio.h>struct S1 {short a;long b; };struct S2 {char c;struct S1 d;double e; };int main() {printf("sizeof(struct S1) = %d\n", sizeof(struct S1));printf("sizeof(struct S2) = %d\n", sizeof(struct S2));return 0; }

    運行結果為:

    sizeof(struct S1) = 8
    sizeof(struct S2) = 20

    S1很好分析。下面我們分析S2

    struct S2 //對齊方式 大小 起始地址 占用的內存地址位置 {char c; 4 大于 1(對齊參數) 0 0 struct S1 d; 4 等于 4(這個是S1中最大參數大小) 4(4整除) 4~11(S1實際大小為8double e; 4(對齊)小于 8 12(4整除) 12~19 };

    注意: 上面S2中的S1實際大小是8,那個4是作為與對齊方式比較時(選取較小的作為對齊參數)選取S1中最大的數據成員大小。

  • S2 的對齊方式是4字節對齊
  • 然后再根據:

  • 每個成員按其類型大小和pack參數中較小的一個 進行對齊。比如上面的起始地址計算那里,對齊參數分別為0,4,12

    2.1 偏移地址必須能被對齊參數整除
    2.2 如果一個結構體中有一個變量也是結構體,那么這個內部的結構體成員的對齊大小就按照其內部最大的數據成員作為其大小來計算

  • 這一條規則計算每個成員的起始地址。如上面的計算。

  • 最后再看總體大小是否是對齊參數的整數倍。上面S2 大小是20,是對齊參數4的整數倍
  • 我所使用的編譯器gcc 4.4.5 不支持8字節對齊方式

    3 總結

    注意好好理解上述計算結構體大小的計算方法。然后自己畫畫內存圖。

    總結

    以上是生活随笔為你收集整理的【C语言进阶深度学习记录】二十 结构体大小计算与结构体内存布局的详细方法的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。