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

結(jié)構(gòu)體對齊的規(guī)則詳解及C++代碼驗證

 更新時間:2021年08月16日 16:42:12   投稿:BJT  
在c語言的結(jié)構(gòu)體里面一般會按照某種規(guī)則去進(jìn)行字節(jié)對齊。本文就來介紹一下如何實現(xiàn),具有一定的參考價值,感興趣的可以了解下

基本概念

CPU一次能讀取多少個字節(jié)的數(shù)據(jù)主要是看數(shù)據(jù)總線是多少位的,16位CPU一次能讀取2個字節(jié),32位CPU一次能讀取4個字節(jié),64位CPU一次能讀取8個字節(jié)。并且不能跨內(nèi)存區(qū)間訪問,這句話的意思可以理解為,如果CPU是32位的話,那么可以將整個內(nèi)存區(qū)間每4個字節(jié)分為一塊(BLOCK),每次讀取一個BLOCK的數(shù)據(jù)。

那么對于下面這個結(jié)構(gòu)體:

struct st {
    char c;
    int i;
};

如果不進(jìn)行對齊操作,char 的地址范圍0x00000000,int的地址范圍為0x00000001----0x00000004,int分布在兩個不同的BLOCK上,因此要讀取int需要兩次操作;如果進(jìn)行4字節(jié)對齊,那么int的地址范圍為0x00000004----0x00000007,處在一個BLOCK上,因此只需一次讀取操作即可。缺點也顯而易見,多占用了3個字節(jié)。這也是典型的一種空間換時間的方法吧。

結(jié)構(gòu)體對齊的規(guī)則

結(jié)構(gòu)體對齊需要滿足以下三條規(guī)則,其中系統(tǒng)對齊模數(shù)在64位機器上默認(rèn)為8字節(jié),32位機器上默認(rèn)為4字節(jié)。通過預(yù)處理指令#pargma pack(N)可以修改系統(tǒng)模數(shù)為N個字節(jié)。

1、以結(jié)構(gòu)體第一個元素的地址為起始地址,亦即結(jié)構(gòu)體的起始地址。由上可知,第一個元素的偏移量為0;

2、結(jié)構(gòu)體元素對齊原則:結(jié)構(gòu)體成員的對齊模數(shù)為類型大小與系統(tǒng)對齊模數(shù)的較小者;結(jié)構(gòu)體成員的偏移量(填充)為對齊模數(shù)的整數(shù)倍。

3、結(jié)構(gòu)體大小對齊原則:結(jié)構(gòu)體的對齊模數(shù)為結(jié)構(gòu)體最大元素與系統(tǒng)對齊模數(shù)的較小者;結(jié)構(gòu)體的大小(填充)為結(jié)構(gòu)體對齊模數(shù)的整數(shù)倍。

程序驗證

測試環(huán)境為64位Windows ,VS2019,定義結(jié)構(gòu)體st1,包含3個元素char,int,double,定義系統(tǒng)對齊模數(shù)為4個字節(jié)。

#include <iostream>

#pragma pack(4)

using Tsize = unsigned long long;
using namespace std;

struct st1 {
    char c;
    int i;
    double db;
    Tsize ch_offset() {
        return Tsize((Tsize)&this->c - (Tsize)this);
    }
    Tsize int_offset() {
        return Tsize((Tsize)&this->i - (Tsize)this);
    }
    Tsize double_offset() {
        return Tsize((Tsize)&this->db - (Tsize)this);
    }
};

int main() {
    cout << "st1結(jié)構(gòu)體大小" << sizeof(st1) << endl;
    cout << "char 偏移量=" << st1().ch_offset() << endl;
    cout << "int偏移量=" << st1().int_offset() << endl;
    cout << "double偏移量=" << st1().double_offset() << endl;
    return 0;
}

首先我們按照對齊規(guī)則來進(jìn)行分析。第一個元素為char,類型大小為1個字節(jié),對齊模數(shù)min(1,4)=1,偏移量為0是對齊模數(shù)的整數(shù)倍,無需填充(從這里我們可以看到,第一個字節(jié)偏移量始終為0,是不需要填充的),下一個元素的偏移從1開始;第二個元素為int,類型大小4個字節(jié),對齊模數(shù)為4個字節(jié),不填充時偏移量為1,不是4的整數(shù)倍,因此這里需要填充3個字節(jié),使得int的偏移量為4,且下一個元素偏移從8開始;第三個元素是double,類型大小為8個字節(jié),對齊模數(shù)為4,偏移量從8開始,是4的整數(shù)倍,因此無需填充,占用8個字節(jié),因此結(jié)構(gòu)體的大小為16個字節(jié)。運行程序輸出:

在這里插入圖片描述

將系統(tǒng)對齊模數(shù)修改為1 【#pargma pack(1)】,這樣的話,任何情況下都無需填充(不足一個字節(jié)的類型視為一個字節(jié)),結(jié)構(gòu)體的大小即為結(jié)構(gòu)體元素大小之和。運行程序輸出:

在這里插入圖片描述

將系統(tǒng)對齊模數(shù)修改為8 【#pargma pack(8)】,這樣的話,任何情況下都無需填充(不足一個字節(jié)的類型視為一個字節(jié)),結(jié)構(gòu)體的大小即為結(jié)構(gòu)體元素大小之和。運行程序輸出:

在這里插入圖片描述

Emmm,好像和系統(tǒng)對齊模數(shù)為4時沒什么變化。那我們將int 和 double的順序換一下呢?

#include <iostream>

#pragma pack(8)

using Tsize = unsigned long long;
using namespace std;

struct st1 {
    char c;
    double db;
    int i;
    Tsize ch_offset() {
        return Tsize((Tsize)&this->c - (Tsize)this);
    }
    Tsize int_offset() {
        return Tsize((Tsize)&this->i - (Tsize)this);
    }
    Tsize double_offset() {
        return Tsize((Tsize)&this->db - (Tsize)this);
    }
};

int main() {
    cout << "st1結(jié)構(gòu)體大小" << sizeof(st1) << endl;
    cout << "char 偏移量=" << st1().ch_offset() << endl;
    cout << "double偏移量=" << st1().double_offset() << endl;
    cout << "int偏移量=" << st1().int_offset() << endl;
    return 0;
}

在這里插入圖片描述

順序調(diào)了下,結(jié)構(gòu)體就比原來大了8個字節(jié)!!!從中我們可以看出,將結(jié)構(gòu)體元素從小到大排列,可以最大程度節(jié)省空間。

總結(jié)

本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • OpenCV?直方圖均衡化的實現(xiàn)原理解析

    OpenCV?直方圖均衡化的實現(xiàn)原理解析

    直方圖均衡化是通過拉伸像素強度分布范圍來增強圖像對比度的一種方法,今天通過本文給大家介紹OpenCV?直方圖均衡化的實現(xiàn)原理解析,感興趣的朋友跟隨小編一起看看吧
    2022-01-01
  • C++運行時類型識別與轉(zhuǎn)換實現(xiàn)方法

    C++運行時類型識別與轉(zhuǎn)換實現(xiàn)方法

    運行時類型識別可能被認(rèn)為是C++中一個”次要“的特征,當(dāng)程序員在編程過程中陷入非常困難的境地時,實用主義將會幫助他走出困境
    2022-10-10
  • C++?拷貝構(gòu)造函數(shù)與賦值的區(qū)別

    C++?拷貝構(gòu)造函數(shù)與賦值的區(qū)別

    拷貝構(gòu)造函數(shù)和賦值函數(shù)非常容易混淆,本文主要介紹了C++?拷貝構(gòu)造函數(shù)與賦值的區(qū)別,具有一定的參考價值,感興趣的可以了解一下
    2024-04-04
  • 利用C++單例模式實現(xiàn)高性能配置管理器

    利用C++單例模式實現(xiàn)高性能配置管理器

    這篇文章主要為大家詳細(xì)介紹了如何利用C++單例模式實現(xiàn)高性能配置管理器,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下
    2023-04-04
  • C語言實現(xiàn)輸出鏈表中倒數(shù)第k個節(jié)點

    C語言實現(xiàn)輸出鏈表中倒數(shù)第k個節(jié)點

    這篇文章主要介紹了C語言實現(xiàn)輸出鏈表中倒數(shù)第k個節(jié)點,主要涉及鏈表的遍歷操作,是數(shù)據(jù)結(jié)構(gòu)中鏈表的常見操作。需要的朋友可以參考下
    2014-09-09
  • C++成員初始化列表

    C++成員初始化列表

    這篇文章主要介紹了C++成員初始化列表,除了可以使用構(gòu)造函數(shù)對類成員進(jìn)行初始化之外,C++還提供了另外一種初始化的方法,叫做成員初始化列表。下面來看看文章的詳細(xì)吧,需要的朋友可以參考一下
    2022-01-01
  • 深入分析C語言存儲類型與用戶空間內(nèi)部分布

    深入分析C語言存儲類型與用戶空間內(nèi)部分布

    這篇文章主要介紹了C語言存儲類型與用戶空間內(nèi)部分布,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-12-12
  • C++之list容器模擬實現(xiàn)方式

    C++之list容器模擬實現(xiàn)方式

    這篇文章主要介紹了C++之list容器模擬實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • C語言斷言函數(shù)assert()的學(xué)習(xí)筆記

    C語言斷言函數(shù)assert()的學(xué)習(xí)筆記

    在C語言庫函數(shù)中提供了一個輔助調(diào)試程序的小型庫,它是由assert()宏組成,本文就詳細(xì)的介紹了一下如何使用,感興趣的可以了解一下
    2021-11-11
  • C++去除輸入行中空白的方法

    C++去除輸入行中空白的方法

    這篇文章主要介紹了C++去除輸入行中空白的方法,涉及C++針對數(shù)組的遍歷與替換的相關(guān)使用技巧,需要的朋友可以參考下
    2015-07-07

最新評論