1. 程式人生 > >關於面試題中結構體記憶體對齊計算總結

關於面試題中結構體記憶體對齊計算總結

記憶體對齊計算可謂是筆試題的必考題,但是如何按照計算原則算出正確答案一開始也不是很容易的事,所以專門通過例子來複習下關於結構體記憶體對齊的計算問題。(編譯環境為vs2015)

對齊原則:

原則1:資料成員對齊規則:結構(struct)(或聯合(union))的資料成員,第一個資料成員放在offset為0的地方,以後每個資料成員的對齊按照#pragma pack指定的數值和這個資料成員自身長度中,比較小的那個進行。

原則2:結構(或聯合)的整體對齊規則:在資料成員完成各自對齊之後,結構(或聯合)本身也要進行對齊,對齊將按照#pragma pack指定的數值和結構(或聯合)最大資料成員長度中,比較小的那個進行。

原則3:結構體作為成員:如果一個結構裡有某些結構體成員,則結構體成員要從其內部最大元素大小的整數倍地址開始儲存。

預設對齊值:

Linux 預設#pragma pack(4)

window 預設#pragma pack(8)

注:可以通過預編譯命令#pragma pack(n),n=1,2,4,8,16來改變這一系數,其中的n就是指定的“對齊係數”。

例一:一位元組對齊

第一步: 成員資料對齊

#pragma pack(1)
struct AA {
    int a;   //長度4 < 1 按1對齊;偏移量為0;存放位置區間[0,3]
    char
b; //長度1 = 1 按1對齊;偏移量為4;存放位置區間[4] short c; //長度2 > 1 按1對齊;偏移量為5;存放位置區間[5,6] char d; //長度1 = 1 按1對齊;偏移量為6;存放位置區間[7] //整體存放在[0~7]位置區間中,共八個位元組。 }; #pragma pack()

第二步: 整體對齊

整體對齊係數 = min((max(int,short,char), 1) = 1,所以不需要再進行整體對齊。整體大小就為8。

圖示如下:

這裡寫圖片描述

例二:二位元組對齊

第一步: 成員資料對齊

#pragma pack(2)
struct AA {
    int a;   //長度4 > 2 按2對齊;偏移量為0;存放位置區間[0,3]
char b; //長度1 < 2 按1對齊;偏移量為4;存放位置區間[4] short c; //長度2 = 2 按2對齊;偏移量要提升到2的倍數6;存放位置區間[6,7] char d; //長度1 < 2 按1對齊;偏移量為7;存放位置區間[8];共九個位元組 }; #pragma pack()

第二步: 整體對齊

整體對齊係數 = min((max(int,short,char), 2) = 2,將9提升到2的倍數,則為10.所以最終結果為10個位元組。

圖示如下:(X為補齊部分)

這裡寫圖片描述

例三:四位元組對齊

第一步: 成員資料對齊

#pragma pack(4)
struct AA {
    int a;   //長度4 = 4 按4對齊;偏移量為0;存放位置區間[0,3]
    char b;  //長度1 < 4 按1對齊;偏移量為4;存放位置區間[4]
    short c; //長度2 < 4 按2對齊;偏移量要提升到2的倍數6;存放位置區間[6,7]
    char d;  //長度1 < 4 按1對齊;偏移量為7;存放位置區間[8];總大小為9
};
#pragma pack()

第二步: 整體對齊

整體對齊係數 = min((max(int,short,char), 4) = 4,將9提升到4的倍數,則為12.所以最終結果為12個位元組。

圖示如下:(X為補齊部分)

這裡寫圖片描述

例三:八位元組對齊

第一步: 成員資料對齊

#pragma pack(8)
struct AA {
    int a;   //長度4 < 8 按4對齊;偏移量為0;存放位置區間[0,3]
    char b;  //長度1 < 8 按1對齊;偏移量為4;存放位置區間[4]
    short c; //長度2 < 8 按2對齊;偏移量要提升到2的倍數6;存放位置區間[6,7]
    char d;  //長度1 < 8 按1對齊;偏移量為7;存放位置區間[8],總大小為9
};
#pragma pack()

第二步: 整體對齊

整體對齊係數 = min((max(int,short,char), 8) = 4,將9提升到4的倍數,則為12.所以最終結果為12個位元組。圖示如上。

注:可以通過stddef.h庫中的offsetof巨集來檢視對應結構體元素的偏移量。

例四:結構體中包含結構體的運算

整體計算過程如下

struct EE
{
    int a;      //長度4 < 8 按4對齊;偏移量為0;存放位置區間[0,3]
    char b;     //長度1 < 8 按1對齊;偏移量為4;存放位置區間[4]
    short c;    //長度2 < 8 按2對齊;偏移量由5提升到6;存放位置區間[6,7]
    //結構體內部最大元素為int,由於偏移量為8剛好是4的整數倍,所以從8開始存放接下來的struct FF
    struct FF
    {
        int a1;     //長度4 < 8 按4對齊;偏移量為8;存放位置區間[8,11]
        char b1;    //長度1 < 8 按1對齊;偏移量為12;存放位置區間[12]
        short c1;   //長度2 < 8 按2對齊;偏移量為13,提升到2的倍數14;存放位置區間[14,15]
        char d1;    //長度1 < 8 按1對齊;偏移量為16;存放位置區間[16]
    };
    //整體對齊係數 = min((max(int,short,char), 8) = 4,將記憶體大小由17補齊到4的整數倍20
    char d;         //長度1 < 8 按1對齊;偏移量為21;存放位置區間[21]
    //整體對齊係數 = min((max(int,short,char), 8) = 4,將記憶體大小由21補齊到4的整數倍24
};

圖示如下:

這裡寫圖片描述

例五:再來一個巢狀結構體的計算

整體計算過程如下

struct B {
    char e[2];      //長度1 < 8 按2對齊;偏移量為0;存放位置區間[0,1]
    short h;        //長度2 < 8 按2對齊;偏移量為2;存放位置區間[2,3]
    //結構體內部最大元素為double,偏移量為4,提升到8,所以從8開始存放接下來的struct A
    struct A {
        int a;      //長度4 < 8 按4對齊;偏移量為8;存放位置區間[8,11]
        double b;   //長度8 = 8 按8對齊;偏移量為12,提升到16;存放位置區間16,23]
        float c;    //長度4 < 8,按4對齊;偏移量為24,存放位置區間[24,27]
    };
    //整體對齊係數 = min((max(int,double,float), 8) = 8,將記憶體大小由28補齊到8的整數倍32
};

圖示如下:

這裡寫圖片描述

小結:當#pragma pack的n值等於或超過所有資料成員長度的時候,這個n值的大小將不產生任何效果。

相關推薦

關於試題結構記憶體計算總結

記憶體對齊計算可謂是筆試題的必考題,但是如何按照計算原則算出正確答案一開始也不是很容易的事,所以專門通過例子來複習下關於結構體記憶體對齊的計算問題。(編譯環境為vs2015) 對齊原則: 原則1:資料成員對齊規則:結構(struct)(或聯合(un

結構記憶體計算問題總結大全

前言本文給大家介紹的是關於C++結構體記憶體對齊計算的相關內容,記憶體對齊計算可謂是筆試題的必考題,但是如何按照計算原則算出正確答案一開始也不是很容易的事,所以專門通過例子來複習下關於結構體記憶體對齊的計算問題。話不多說,來一起看看詳細介紹吧。編譯環境:vs2015對齊原則:

結構記憶體模式

結構體的位元組大小,一個簡單的結構體定義如下,這個結構的大小應是8位元組(32位下) typedef struct MODEL4 { char c; int x; }MODEL4; char的大小是1,而int是4,但總的大小是8,這就是結構體記憶體對齊的原因。在32位的機器上,資料是以

結構記憶體總結

  首先我們都知道結構體是多個變數的集合,在其中可以存放整型,浮點型等等各種,然後結構體記憶體是如何對齊的呢,他並不是按連續順序去排下去的,首先我們先上一段程式碼 #include<iostream> #include<cstdlib> using namesp

初夏小談:結構記憶體詳解

記憶體對齊?什麼是記憶體對齊? 對於這個問題我們先來看看這樣的一個結構體(在32位系統下) typedef struct Stu1 { char C1; int num1; short S1; }Stu1; 如果我們不知道記憶體對齊或者不清楚記憶體對齊時,我們可能這樣分析

C++結構方式

在面試中,常會考到結構體的對齊方式,因此對其進行總結。 1、在沒有#pragma pack巨集的情況下     struct sA{ double d1; int i1; double d2; char c1;

C語言查缺補漏(七)結構記憶體原則

忽略點七:結構體記憶體對齊原則 ​ 直到前幾個星期做了一道選擇題才知道,結構體元素的宣告順序可能影響結構體使用時所需的記憶體大小!!! ​ 一查才知道,在C語言中結構體有記憶體對齊原則,這個原則可以總結為兩點: ——資料成員對齊規則: ​ 結構體或聯合體的資料

結構結構記憶體

1、結構體 1.1、概述 在C語言中,除了常見的基本資料型別(整數型別short、int、long和浮點型別float、double)外,還有派生型別,如指標型別、陣列型別、結構型別、共用體型別等。 結構體是基本資料型別不能滿足需求時,使用者自己指定的一種資料結

結構記憶體,位段,列舉+聯合

1.結構體記憶體對齊 結構體記憶體對齊規則 1.第一個成員在與結構體變數偏移量為0的地址處 2.其他成員變數要對齊到對齊數的整數倍的地址處。對齊數=編譯器預設的一個對齊數與該成員大小的 較小值   vs中預設的值為8,linux中的預設值為4 3.結構體總大小為最

結構記憶體問題

問題描述: 結構體記憶體對齊問題值直接的體現就是計算結構體的sizeof佔用的位元組數。 結構體記憶體對齊的幾個原則,有了這幾個原則,不管結構體裡面是什麼元素,我們都能夠正確算出sizeof值(以VS2013為例) 原則1: 結構體中每一個元素放置到記憶體中時,它都會認為記憶體

【易錯】C語言結構記憶體問題

對於一個結構體的位元組數大家有沒有遇到什麼疑問呢? 先看一個結構體: typedef struct Test { char a1; int a2; char a3; short a4; }Test_T; 在32位編譯系統下這一個結構體的位元組數是多少呢?是1+4

1.結構體型別建立 2.結構初始化 3.結構記憶體 4.位段,位段計算機大小。 5.列舉 6.聯合

結構體型別的建立 1.結構體的宣告 結構是一些值的集合,這些值稱為成員變數。每個結構體的成員可以是不同型別的變數。 struct Student { char name[20];//名字 short age;//年齡 char sex[5

C++學習:結構記憶體規則

記憶體對齊舉例: 以下兩個結構體: #include<iostream> using namespace std; struct A{ char a; int b; short c; }; struct B{

結構記憶體和強制型別轉換問題分析

最近兩天覆習c++的連結串列的時候發現了一個問題值得深思. 首先從一個現象上引出問題: 在我寫線性表的鏈式儲存的時候定義了幾個結構體:(全部程式碼在這裡) linklist.h typedef void LinkList; typedef struct

跟我一起學C++之從C到C++(結構記憶體

1.什麼是記憶體對齊 (1)      編譯器為每個“資料單元”按排在某個合適的位置上。 (2)      C、C++語言非常靈活,它允許你干涉“記憶體對齊”。也就是可以人為的設定編譯器的對齊方式。 2.為什麼要對齊 效能原因:在對齊的地址上訪問資料快。如果是位元組對齊方式

為什麼要進行結構記憶體

結構體記憶體對齊 什麼是結構體記憶體對齊 結構體不像陣列,結構體中可以存放不同型別的資料,它的大小也不是簡單的各個資料成員大小之和,限於讀取記憶體的要求,而是每個成員在記憶體中的儲存都要按照一定偏移量來儲存,根據型別的不同,每個成員都要按照一定的對齊數進

C語言-----結構記憶體

結構體記憶體對齊規則: 第一個成員在結構體變數偏移量為0 的地址處。 其他成員變數要對齊到某個數字(對齊數)的整數倍的地址處。對齊數 = 編譯器預設的一個對齊數與該成員大小中的較小值。vs中預設值是8 Linux預設值為4. 結構體總大小為最大對齊數的整數

結構記憶體原則

1.結構體對齊含義 Ø 結構體的儲存結構 Ø  結構體的總大小(sizeof) 2.結構體對齊原則 Ø  結構體是按照成員定義順序儲存的 Ø  結構體第一個成員從offset為0的地址開始儲存 Ø  成員儲存起始地址必須滿足:min(“成員自身型別的模數”,“#pragam

c++結構記憶體原理和方法

假設我們同時宣告兩個變數:  char a;  short b;  用&(取地址符號)觀察變數a,  b的地址的話,我們會發現(以16位CPU為例):  如果a的地址是0x0000,那麼b的地址將會是0x0002或者是0x0004。  那麼就出現這樣一個問題:0x0001這個地址沒有被使用,那它幹

STM32學習筆記10——stm32結構位元組問題

stm32做串列埠或網路傳輸資料時,經常需要用結構體定義幀格式。如果按照keil預設的對齊方式(4位元組對齊),經常會出現結構體中補零的問題,造成幀格式錯誤。所以,在定義結構體型別時,最好把結構體對齊方式改為1位元組對齊,防止出錯。理論和方法見下面轉載的文章。 #pra