亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

深入理解c/c++ 內存對齊

2020-01-26 15:38:21
字體:
來源:轉載
供稿:網友

內存對齊,memory alignment.為了提高程序的性能,數據結構(尤其是棧)應該盡可能地在自然邊界上對齊。原因在于,為了訪問未對齊的內存,處理器需要作兩次內存訪問;然而,對齊的內存訪問僅需要一次訪問。
內存對齊一般講就是cpu access memory的效率(提高運行速度)和準確性(在一些條件下,如果沒有對齊會導致數據不同步現象).依賴cpu,平臺和編譯器的不同.一些cpu要求較高(這句話說的不準確,但是確實依賴cpu的不同),而有些平臺已經優化內存對齊問題,不同編譯器的對齊模數不同.總的來說內存對齊屬于編譯器的問題.

一般情況下不需要理會內存對齊問題,內存對齊是編譯器的事情.但碰到一些問題上還是需要理解這個概念.畢竟c/c++值直接操作內存的語言.需要理解程序在內存中的分布和運行原理.

總之一句話就是:不要讓代碼依賴內存對齊.


1.原因:為什么需要內存對齊.
1、平臺原因(移植原因):不是所有的硬件平臺都能訪問任意地址上的任意數據的;某些硬件平臺只能在某些地址處取某些特定類型的數據,否則拋出硬件異常。

2、性能原因:數據結構(尤其是棧)應該盡可能地在自然邊界上對齊。原因在于,為了訪問未對齊的內存,處理器需要作兩次內存訪問;而對齊的內存訪問僅需要一次訪問。


2.內存對齊的規則和范例
講述內存對齊之前先看下各種類型的大小,和編譯器以及字長有關具體在此不多敘述.
具體帖子:http://blog.csdn.net/lyl0625/article/details/7350045
成員的內存分配規律:從結構體的首地址開始向后依次為每個成員尋找第一個滿足條件的首地址x,該條件是x % N = 0,并且整個結構的長度必須為各個成員所使用的對齊參數中最大的那個值的最小整數倍,不夠就補空字節。
結構體中所有成員的對齊參數N的最大值稱為結構體的對齊參數。

1、數據成員對齊規則:結構(struct)(或聯合(union))的數據成員,第一個數據成員放在offset為0的地方,以后每個數據成員的對齊按照#pragma pack指定的數值(或默認值)和這個數據成員類型長度中,比較小的那個進行。在上一個對齊后的地方開始尋找能被當前對齊數值整除的地址.
2、結構(或聯合)的整體對齊規則:在數據成員完成各自對齊之后,結構(或聯合)本身也要進行對齊.主要體現在,最后一個元素對齊后,后面是否填補空字節,如果填補,填補多少.對齊將按照#pragma pack指定的數值(或默認值)和結構(或聯合)最大數據成員類型長度中,比較小的那個進行。
3、結合1、2顆推斷:當#pragma pack的n值等于或超過所有數據成員類型長度的時候,這個n值的大小將不產生任何效果。
兩點注意:數組,嵌套結構體.
數組:
對齊值為:min(數組元素類型,指定對齊長度).但數組中的元素是連續存放,存放時還是按照數組實際的長度.
如char t[9],對齊長度為1,實際占用連續的9byte.然后根據下一個元素的對齊長度決定在下一個元素之前填補多少byte.
嵌套的結構體:
假設
struct A
{
......
struct B b;
......
};
對于B結構體在A中的對齊長度為:min(B結構體的對齊長度,指定的對齊長度).
B結構體的對齊長度為:上述2中結構整體對齊規則中的對齊長度.

例子:
VC++6.0中n 默認是8個字節,可以修改這個設定的對齊參數
也可以采用指令:#pragma   pack(xx)控制.

1.基礎例子

復制代碼 代碼如下:

#pragma   pack(n)
struct A
{
char   c; //1byte
double d; //8byte
short s; //2byte
int i; //4byte
};
int main(int argc, char* argv[])
{
A strua;
printf("%len:d/n",sizeof(A));
printf("%d,%d,%d,%d",&strua.c,&strua.d,&strua.s,&strua.i);
return 0;
}

1)n設置為8byte時
結果:len:24,
1245032,1245040,1245048,1245052
內存中成員分布如下:
strua.c分配在一個起始于8的整數倍的地址1245032(為什么是這樣讀者先自己思考,讀完就會明白),接下來要在strua.c之后分配strua.d,由于double為8字節,取N=min(8,8),8字節來對齊,所以從strua.c向后找第一個能被8整除的地址,所以取1245032+8得1245040, strua.s 為2byte小于參數n,所以N=min(2,8),即N=2,取2字節長度對齊,所以要從strua.d后面尋找第一個能被2整除的地址來存儲strua.s,由于strua.d后面的地址為1245048可以被2整除,所以strua.s緊接著分配,現在來分配strua.i,int為4byte,小于指定對齊參數8byte,所以N=min(4,8)取N=4byte對齊,strua.s后面第一個能被4整除地址為1245048+4,所以在1245048+4的位置分配了strua.i,中間補空,同時由于所有成員的N值的最大值為8,所以整個結構長度為8byte的最小整數倍,即取24byte其余均補0.
于是該結構體的對齊參數就是8byte。
2)當對齊參數n設置為16byte時,結果同上,不再分析
3)當對齊參數設置為4byte時
上例結果為:Len:20
1245036,1245040,1245048,1245052
內存中成員分布如下:
Strua.c起始于一個4的整數倍的地址,接下來要在strua.c之后分配strua.d,由于strua.d長度為8byte,大于對齊參數4byte,所以N=min(8,4)取最小的4字節,所以向后找第一個能被4整除的地址來作為strua.d首地址,故取1245036+4,接著要在strua.d后分配strua.s,strua.s長度為2byte小于4byte,取N=min(2,4)2byte對齊,由于strua.d后的地址為1245048可以被2
整除,所以直接在strua.d后面分配,strua.i的長度為4byte,所以取N=min(4,4)4byte對齊,所以從strua.s向后找第一個能被4整除的位置即1245048+4來分配和strua.i,同時N的最大值為4byte,所以整個結構的長度為4byte的最小整數倍20byte
4)當對齊參數設置為2byte時
上例結果為:Len:16
1245040,1245042,1245050,1245052
Strua.c分配后,向后找一第一個能被2整除的位置來存放strua.d,依次類推
5)1byte對齊時:
上例結果為:Len:15
1245040,1245041,1245049,1245051
此時,N=min(sizeof(成員),1),取N=1,由于1可以整除任何整數,所以各個成員依次分配,沒有間空.
6)當結構體成員為數組時,并不是將整個數組當成一個成員來對待,而是將數組的每個元素當一個成員來分配,其他分配規則不變,如將上例的結構體改為:
struct A
{
char c; //1byte
double d; //8byte
short s; //2byte
char  szBuf[5];
};
對齊參數設置為8byte,則,運行結果如下:
Len:24
1245032,1245040,1245048,1245050
Strua 的s分配后,接下來分配Strua 的數組szBuf[5],這里要單獨分配它的每個元素,由于是char類型,所以N=min(1,8),取N=1,所以數組szBuf[5]的元素依次分配沒有間隙。

看完上述的例子,基本分配的規律和方法應該已經知道.下面主要說明數組,嵌套結構體,指針時的一些內存對齊問題.
最重要的是自己寫程序證明.

2.數組,嵌套.
測試環境:64位 ubuntu;g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3

復制代碼 代碼如下:

#include <iostream>
#include <cstdio>
using namespace std;
#pragma pack(8)
struct Args
{
        char ch;
        double d;
        short st;
        char rs[9];
        int i;
} args;
struct Argsa
{
        char ch;
        Args test;
        char jd[10];
        int i;
}arga;

int main()
{
// cout <<sizeof(char)<<" "<<sizeof(double)<<" "<<sizeof(short)<<" "<<sizeof(int)<<endl;
//cout<<sizeof(long)<<" "<<sizeof(long long)<<" "<<sizeof(float)<<endl;
cout<<"Args:"<<sizeof(args)<<endl;
cout<<""<<(unsigned long)&args.i-(unsigned long)&args.rs<<endl;
cout<<"Argsa:"<<sizeof(arga)<<endl;
cout<<"Argsa:"<<(unsigned long)&arga.i -(unsigned long)&arga.jd<<endl;
cout<<"Argsa:"<<(unsigned long)&arga.jd-(unsigned long)&arga.test<<endl;
return 0;
}

輸出結果:
Args:32
10
Argsa:56
Argsa:12
Argsa:32

struct Args長度32 struct Argsa長度:56.
改成#pragma pack (16)結果一樣.
這個例子證明了三點:
對齊長度長于struct中的類型長度最長的值時,設置的對齊長度等于無用.
數組對齊的長度是按照數組成員類型長度來比對的.
嵌套的結構體中,所包含的結構體的對齊長度是結構體的對齊長度.

3.指針.主要是因為32位和64位機尋址上
測試環境同2.(64位系統)

復制代碼 代碼如下:

#include <iostream>
#include <cstdio>
#pragma pack(4)
using namespace std;

struct Args
{
        int i;
        double d;
        char *p;
        char ch;
        int *pi;
}args;
int main()
{   
        cout<<"args length:"<<sizeof(args)<<endl;
        cout<<(unsigned long)&args.ch-(unsigned long)&args.p<<endl;
        cout<<(unsigned long)&args.pi-(unsigned long)&args.ch<<endl;
        return 0;
}

設置pack為4時:
args length:32
8
4

設置pack為8時:
args length:40
8
8
看了上述內容,應該能分析出來為什么是這個結果.這里不詳細描述.

3.不同編譯器中內存對齊
VC 6.0上是8 byte

gcc 默認是8byte.測試版本gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
g++默認是8byte.測試版本g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
但查閱的資料說是gcc 默認是4,且不支持pragma參數設定.測試的時候gcc默認對齊為8byte且,支持pragma參數.
測試過兩個不同的例子,結果相同.

4.什么時候需要進行內存對齊.
一般情況下都不需要對編譯器進行的內存對齊規則進行修改,因為這樣會降低程序的性能,除非在以下兩種情況下:

(1)這個結構需要直接被寫入文件;

(2)這個結構需通過網絡傳給其他程序;

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品福利一区二区| 国产精品免费观看在线| 亚洲天堂成人在线视频| 亚洲成av人影院在线观看| 亚洲人成网站999久久久综合| 免费91在线视频| 久久精品99久久久久久久久| 国产成人涩涩涩视频在线观看| 国产精品海角社区在线观看| 国产女精品视频网站免费| 国产精品久久一| 欧美日韩成人黄色| 国产视频在线一区二区| 欧美—级a级欧美特级ar全黄| 国产精品国语对白| 亚洲男人的天堂在线| 国产精品成人aaaaa网站| 九九热99久久久国产盗摄| 成人午夜两性视频| 日韩av最新在线| 国产精品国产三级国产专播精品人| 国产性猛交xxxx免费看久久| 成人激情视频免费在线| 日韩欧美有码在线| 国产在线播放不卡| 亚洲精品国产精品国产自| 国产精品免费电影| 欧美xxxx14xxxxx性爽| 久久99精品久久久久久噜噜| 久久久久久香蕉网| 国产精品视频免费在线观看| 91精品国产色综合| 精品成人久久av| 亚洲偷熟乱区亚洲香蕉av| 亚洲人在线视频| 成人福利免费观看| 亚洲天堂男人天堂| 日韩综合视频在线观看| 欧美激情亚洲综合一区| 久久精品国产一区二区电影| 久久亚洲综合国产精品99麻豆精品福利| 国产视频精品免费播放| 国内偷自视频区视频综合| 日韩av男人的天堂| 成人精品久久久| 秋霞成人午夜鲁丝一区二区三区| 亚洲欧美制服丝袜| 中文字幕一区电影| 91精品视频在线看| 色先锋资源久久综合5566| 日本欧美爱爱爱| 欧美日韩一区二区三区在线免费观看| 尤物精品国产第一福利三区| 欧美性猛xxx| 欧美极品第一页| 国产精品夜间视频香蕉| 97视频免费观看| 欧美日韩一区二区在线| 亚洲欧美中文日韩在线v日本| 黑人巨大精品欧美一区二区免费| 一本色道久久综合狠狠躁篇怎么玩| 欧美日韩福利在线观看| 欧美日韩在线视频首页| 久久精品视频亚洲| 一区二区在线视频| 久久男人资源视频| 日韩视频一区在线| 亚洲欧美日韩另类| 久久久99久久精品女同性| 欧美成人国产va精品日本一级| 亚洲一品av免费观看| 久久韩国免费视频| 欧美电影在线观看高清| 亚洲综合中文字幕在线| 欧美性猛交99久久久久99按摩| 精品国产91久久久| 欧美人与性动交| 亚洲午夜久久久久久久| 亚洲国产精品va在线看黑人| 色香阁99久久精品久久久| 欧美精品福利视频| 欧美日韩aaaa| 奇米4444一区二区三区| 久久久国产成人精品| 18久久久久久| 欧美日韩国产999| 精品国产精品三级精品av网址| 日韩精品高清在线| 深夜福利国产精品| 中文字幕9999| 97久久超碰福利国产精品…| 色黄久久久久久| 亚洲精品狠狠操| 亚洲视频日韩精品| 欧美一区深夜视频| 欧美黄色片免费观看| 亚洲精品456在线播放狼人| 国产精品久久久久久久久影视| 亚洲欧美国内爽妇网| 欧美理论在线观看| 欧美日韩国产精品一区二区不卡中文| 国产不卡精品视男人的天堂| 日本aⅴ大伊香蕉精品视频| 高清欧美性猛交xxxx黑人猛交| 亚洲一区二区三区在线视频| 欧美激情久久久久久| 91在线国产电影| 日本久久久a级免费| 欧美成人免费在线观看| 一色桃子一区二区| 成人深夜直播免费观看| 久久久久久国产精品三级玉女聊斋| 久久91精品国产91久久久| 欧美国产第二页| 日韩免费电影在线观看| 在线精品高清中文字幕| 国产偷国产偷亚洲清高网站| 欧美视频一区二区三区…| 久久视频中文字幕| 午夜精品久久久久久久99热| 国产精品偷伦视频免费观看国产| 最近2019中文字幕在线高清| 色吧影院999| 色先锋资源久久综合5566| 高清欧美性猛交xxxx黑人猛交| 91网站在线免费观看| 亚洲女人天堂成人av在线| 色播久久人人爽人人爽人人片视av| 亚洲高清免费观看高清完整版| 91精品一区二区| 久久免费视频这里只有精品| 欧美视频在线观看 亚洲欧| 欧美高清第一页| 久久影院中文字幕| 亚洲精品999| 欧美国产日韩在线| 国产精欧美一区二区三区| 久久久久久成人精品| 久久久久久久一区二区| 欧美高清视频在线播放| 亚洲第一福利视频| 51视频国产精品一区二区| 日韩在线国产精品| 日韩中文字幕在线免费观看| 91丝袜美腿美女视频网站| 国产日韩中文字幕在线| 欧美美女15p| xxxx性欧美| 亚洲成人激情在线观看| 91精品国产高清久久久久久| 亚洲精品动漫100p| 成人免费高清完整版在线观看| 视频在线观看一区二区| 成人国产精品免费视频| 亚洲四色影视在线观看| 国产69久久精品成人| 亚洲成人精品久久| 亚洲va欧美va国产综合剧情| 国产精选久久久久久| 91精品久久久久久久久久久久久久| 亚洲第一偷拍网| 亚洲aⅴ日韩av电影在线观看| 欧美激情精品久久久久久蜜臀| 91av在线免费观看|