1. 程式人生 > >跟我一起學C++之從C到C++(結構體記憶體對齊)

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

1.什麼是記憶體對齊

(1)      編譯器為每個“資料單元”按排在某個合適的位置上。

(2)      C、C++語言非常靈活,它允許你干涉“記憶體對齊”。也就是可以人為的設定編譯器的對齊方式。

2.為什麼要對齊

效能原因:在對齊的地址上訪問資料快。如果是位元組對齊方式儲存的話,CPU讀取的時候只需要進行一個匯流排週期即可全部讀取完畢,如果不對齊的話,對於32位的系統,CPU讀取的時候一般架構都是從偶地址開啟的,一次只能讀取4個位元組,因此需要兩個匯流排週期才能完成,並且還需要進行暫存器裡面的資料合併,還需要進行資料移位那麼這樣的效率就是很低的。

3.如何對齊

(1)      第一個資料成員放在offset為0的位置

(2)      其它成員對齊至min(sizeof(member),#pragma pack所指定的值)的整數倍。

(3)整個結構體也要對齊,結構體總大小對齊至各個成員中最大對齊數的整數倍。

程式碼示例:

//main.cpp
#include <iostream>
using namespace std;
#include <stdio.h>

#pragma pack(2)//修改對齊數
struct Test
{
	char a;//1個位元組
	double b;//8個位元組
	char c;//1個位元組
};
#pragma pack()

//對齊規則
//1.第一個成員與結構體變數的偏移量為0。也就是&test = &test.a;
//2.其它成員要對齊到某個數字(對齊數)的整倍數的地址
//3.對齊數取編譯器預設的一個對齊整數與該成員大小的較小值,VS中是預設值是8,所以上述打印出來就是24,取值可以是1,2,4,8,16
//4.結構體總大小為最大對齊數的整數倍


int main(void)
{
	Test test;
	//&test = &test.a;
	char *p= (char*)&test;
	//cout<<p<<endl;
	printf("結構體起始地址:%p\n", p);
	p = &test.a;
	printf("a起始地址:%p\n", p);
	p = (char *)&test.b;
	printf("b起始地址:%p\n", p);
	p = &test.c;
	printf("c起始地址:%p\n", p);

	cout<<sizeof(Test)<<endl;
	return 0;
}

執行結果:


以上例結構體為例,取值範圍在VS中和在linux系統中的g++編譯器,不同的對齊數的起止偏移地址,以及佔用位元組數如下所示:

編譯器

VS

G++

對齊數

起始地址--結束地址

佔用位元組數

起始地址--結束地址

佔用位元組數

1

a:0--0

b:1—9

c:10-10

10

a:0--0

b:1—9

c:10-10

10

2

a:0--1

b:2—10

c:11-12

12

a:0--1

b:2—10

c:11-12

12

4

a:0--3

b:4—11

c:12-15

16

a:0--3

b:4—11

c:12-15

16

8

a:0--7

b:8—15

c:16-24

24

不支援

不支援

16

a:0--15

b:16—31

c:32-47

48

不支援

不支援


相關推薦

一起C++CC++bool型別

bool型別 C++新增型別,表示邏輯真與假 1.邏輯型也稱布林型,其取值為true(邏輯真)和false(邏輯假),儲存位元組數在不同編譯系統中可能有所不同,VC++中為1個位元組。 2.宣告方式:boolresult;result=true; 3.可以當作整數用(tru

一起C++CC++結構記憶體

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

一起Redis高可用主從複製開始

### 前言 現在遇到高併發場景時,快取技術應該算是效能優化的第一步,緩解資料庫壓力的同時還能提高訪問效率,而Redis應該是絕大多數應用場景的首選。但是儘快Redis效能再優秀,在當今高併發場景下,一臺伺服器負責讀寫,機器的效能和記憶體的瓶頸肯定避免不了,到這肯定有小夥伴會想到叢集, 對的,思路沒錯,只是

一起Spark——RDD Join中寬依賴與窄依賴的判斷

1.規律    如果JoinAPI之前被呼叫的RDD API是寬依賴(存在shuffle), 而且兩個join的RDD的分割槽數量一致,join結果的rdd分割槽數量也一樣,這個時候join api是窄依賴   除此之外的,rdd 的join api是寬依賴 2.Join的理解  

一起Spark——《Spark快速大資料分析》pdf版下載

連結:https://pan.baidu.com/s/1vjQCJLyiXzIj6gnCCDyv3g  提取碼:ib01 國慶第四天,去逛了半天的王府井書店,五層出電梯右邊最裡面,倒數第三排《資料結構》,找到了一本很不錯的書《Spark快速大資料分析》,試讀了下,我很喜歡,也很適合

一起Spark——Windows10下spark2.3.0本地開發環境搭建-親測

相關元件版本: JDK1.8.0_171,hadoop-2.7.6,Spark-2.3.0,Scala-2.11.8,Maven-3.5.3,ideaIC-2018.1.4.exe,spark-2.3.0-bin-hadoop2.7 1.1  JDK1.8.0_171 a.&n

一起MongoDB——視覺化工具Compass的簡單使用

首先官方為大家介紹了一下MongoDB Compass的主要功能: 1.對資料的視覺化 2.插入、修改、刪除 3.除錯、優化 進入Compass首先出現連線介面如下(此處我使用的是我操作時候的介面狀態) 直接使用預設None無賬戶連線了嘻嘻嘻 點選綠色CONNEC

一起Spark——資料分割槽

前言         控制資料分佈以獲得最少的網路傳輸可以極大地提升整體效能。         如果給定RDD只需要被掃描一次(例如大小表join中的小表),我們完全沒有必要對其預先進行分割槽處理,只有當資料

一起.NetCore配置變更監聽

**前言** 通常程式中配置少不了,配置的修改也避免不了,配置的熱更新為此給應用程式帶來很大的便捷,不用重啟,提高使用者體驗;但往往有時候需要對修改進行審計,也就是需要記錄,有時候也會針對配置修改的時候觸發相關操作,比如說發郵件通知,或是其他業務操作等,遇到這種情況,配置變更監聽的用處就體現出來了,接下來就

一起.NetCore選項(Options)核心型別簡介

**前言** .NetCore中提供的選項框架,我把其理解為配置組,主要是將服務中可供配置的項提取出來,封裝成一個型別;從而服務可根據應用場景進行相關配置項的設定來滿足需求,其中使用了依賴注入的形式,使得更加簡單、便捷;另外和配置(Configuration)系統的無縫結合,使得服務更加靈活;而對於Opti

一起.NetCore日誌(Log)模型核心

**前言** 魯迅都說:沒有日誌的系統不能上線(魯迅說:這句我沒說過,但是在理)!日誌對於一個系統而言,特別重要,不管是用於事務審計,還是用於系統排錯,還是用於安全追蹤.....都扮演了很重要的角色;之前有很多第三方的日誌框架也很給力,如Log4Net、NLog和Serilog等,在.NetCore中也集成

一起.NetCore日誌作用域及第三方日誌框架擴充套件

前言 上一節對日誌的部分核心型別進行簡單的剖析,相信現在再使用日誌的時候,應該大概知道怎麼一回事了,比如記錄器是怎麼來的,是如何將日誌內容寫入到不同目的地的等;當然還有很多細節沒深入講解,抽時間小夥伴們可以去研究研究;廢話不多說,接下來主要舉例演示日誌作用域及第三方日誌框架的擴充套件; 正文 說到日

一起.NetCore中介軟體(Middleware)簡介和解析請求管道構建

**前言** 中介軟體(Middleware)對於Asp.NetCore專案來說,不能說重要,而是不能缺少,因為Asp.NetCore的請求管道就是通過一系列的中介軟體組成的;在伺服器接收到請求之後,請求會經過請求管道進行相關的過濾或處理; **正文** 那中介軟體是那路大神? 會經常聽說,需要註

一起.NetCore檔案系統應用及核心淺析

**前言** 在開發過程中,肯定避免不了讀取檔案操作,比如讀取配置檔案、上傳和下載檔案、Web中html、js、css、圖片等靜態資源的訪問;在配置檔案讀取章節中有說到,針對不同配置源資料讀取由對應的IConfigurationProvider進行讀取,其實讀取檔案也是一樣,針對於不同型別(物理檔案、嵌入檔

一起.NetCore靜態檔案處理的那些事

**前言** 如今前後端分離開發模式如火如荼,開發職責更加分明(當然前後端一起搞的模式也沒有完全褪去);而對於每個公司產品實施來說,部署模式會稍有差別,有的會單獨將前端檔案部署為一個站點,有的會將前端檔案和後端站點整合一起部署;通常當專案規模比較大的時候,分開站點部署是不錯的選擇,管理和維護清晰,而對於一些

一起.NetCore路由的最佳實現

**前言** 路由,這詞絕對不陌生,不管在前端還是後端都經常提到,而這節不說其他,就聊.NetCore的路由;在之前的Asp.Net MVC 中,路由算是面試時必問的考點,可見其重要性,它的主要作用是對映URL,而不需要關注伺服器的物理檔案結構,提高安全性,同時規範了URL請求,有利於搜尋引擎優化;所以在A

一起RedisRedis概述

**背景** 技術的更新迭代,是程式設計師最最最頭大的事,總是在每個網路角落中有感慨聲:學不動啦; ![img](https://i.loli.net/2020/09/23/Zhsc8k6yUJlHEGW.png) 其實新技術並不是憑空而出,而是隨著業務推進、資料驅動、技術積累促使開發者的不斷探索和實踐

一起.NetCoreSwagger讓前後端不再煩惱及介面自定義

**前言** 隨著前後端分離開發模式的流行,介面對接、聯調成為常事,前端同事會經常問:我需要調哪個介面?這個介面資料格式是啥?條件都傳啥? 對於一些緊急介面可能會採取溝通對接,然後補文件,其他的都會回一句:看文件。 那難道要一邊開發一邊寫文件嗎?早些年是這樣的,但對於後端同事就很不自在了,程式碼敲的正起勁,

一起Redis五種基本型別及其應用場景舉例(幹了6個小時)

**前言** 來啦,老弟?來啦,上一篇就當嘮嘮嗑,接下來就開始進行實操擼命令,計劃是先整體單純說說Redis的各種用法和應用,最後再結合程式碼歸納總結。 Redis預設有16個數據庫(編號為0~15),預設使用第0個,通過命令select任意切換資料庫,和MySql切換資料庫一個道理;各資料庫之間的資

一起.NetCore熟悉的介面許可權驗證不能少(Jwt)

**前言** 許可權管控對於一個系統來說是非常重要的,最熟悉不過的是選單許可權和資料許可權,上一節通過Jwt實現了認證,接下來用它實現介面許可權的驗證,為什麼不是選單許可權呢?對於前後端分離而言,稱其為介面許可權感覺比較符合場景(我是這麼理解的);資料許可權牽涉到具體業務,這裡就不說啦! **正文**