小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

編程基礎(chǔ)|漫淡數(shù)制、碼制、位、字節(jié)、字長及內(nèi)存對齊

 iscowang8998 2019-10-18

數(shù)制、碼制、位、字節(jié)、字長及內(nèi)存對齊等概念具有一定的相關(guān)性:

1 數(shù)制:可用符號數(shù)及模數(shù)

人類最常用的便是10進(jìn)制了,然后還有計時的60進(jìn)制,月份的12進(jìn)制。

計算機(jī)使用的是2進(jìn)制,以及輔助的16進(jìn)制與8進(jìn)制,16和8進(jìn)制與2的乘冪相關(guān)。3個二進(jìn)制位對位一個8進(jìn)制位,4個二進(jìn)制位對應(yīng)一個16進(jìn)制位。

對于n進(jìn)制,有如下規(guī)則:

符號數(shù)量:n-1個;

2進(jìn)制:0,1;8進(jìn)制:0,1,2,3,4,5,6,7;10進(jìn)制:0,1,2,3,4,5,6,7,8,9;16進(jìn)制:0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F(xiàn);

如何表示n呢?需要兩位,也就是10來表示n進(jìn)制的n,n就是n進(jìn)制的模數(shù),當(dāng)某一個數(shù)m與n進(jìn)行求模運(yùn)算時,其結(jié)果都會小于n,如m%n的結(jié)果小于n。

我們知道,計算機(jī)采用二進(jìn)制,是因?yàn)槠溥壿嬙钊菀讓?shí)現(xiàn),具有最佳的穩(wěn)定性。其理論原理來自于布爾代數(shù)和香農(nóng)提出的布爾代數(shù)在開關(guān)電路的實(shí)現(xiàn)。0和1可以用繼電器、晶體管的開關(guān)或電容電信號的有無來實(shí)現(xiàn),且通過門電路(與門、或門、非門等)實(shí)現(xiàn)布爾代數(shù)。

如果單就數(shù)字組合來說,哪一種進(jìn)制的效率最高?先問一個問題:

假設(shè)a*b=N

當(dāng)a取什么值時,a^b的值最大?(a,b可以是小數(shù))。

設(shè)f(x)=x^(K/x),x>0,K是大于0的常數(shù)。對f求導(dǎo),即可得x=e時f取極大值,也是最大值。

e=2.71828……

與e最接近的整數(shù)不是2而是3。

二進(jìn)制存儲的計算機(jī),一個32位的的機(jī)器使用了32個1和0,也就是64個元素,可以表達(dá)2^32=4.29*10^9個精度的數(shù)字。同樣是64個元素,假設(shè)表達(dá)成3^21.3=1.45*10^10,即使是3^21也有1.05*10^10個精度,也就是說,如果用三進(jìn)制,可以有更多的組合,而四進(jìn)制呢?組合數(shù)又變小了(其實(shí)e進(jìn)制有最多的組合數(shù))。

但3進(jìn)制的硬件卻比較難以實(shí)現(xiàn),而二進(jìn)制的組合效率僅次于三進(jìn)制,而硬件實(shí)現(xiàn)最簡單和穩(wěn)定,所以二進(jìn)制是天然的計算機(jī)最佳數(shù)制了,正如黃金是天然的貨幣一樣。

前蘇聯(lián)曾搞過的三進(jìn)制計算機(jī):在一般情況下,命題不一定為真或假,還可能為未知。在三進(jìn)制邏輯學(xué)中,符號1代表真;符號-1代表假;符號0代表未知。三進(jìn)制邏輯電路的電壓存在著三種狀態(tài):正電壓(1)、零電壓(0)和負(fù)電壓(-1)。

2 碼制:萬物編碼

一個以上的符號通過組合規(guī)則便可以描述和表示復(fù)雜的信息了,如摩斯密碼或電碼,英文的字母、中文的漢字。

計算中的底層不管是數(shù)據(jù)還是指令,都是二進(jìn)制的0、1,硬件實(shí)現(xiàn)為晶體管的開關(guān)或電容中電信號的有無。

數(shù)的編碼:包括正整數(shù)的原碼、負(fù)整數(shù)的補(bǔ)碼、浮點(diǎn)數(shù)的IEEE754碼制(包括階碼的移碼);

字符的編碼:如ASCII碼、utf-8的unicode碼,GBK碼等,用不同長度的二進(jìn)制位來表示。

位圖的編碼:位圖像素的數(shù)字化;

聲明的編碼:聲波振幅、頻率采樣的數(shù)字化;

3 數(shù)位:組合、硬件實(shí)現(xiàn)與位運(yùn)算

前面說了,用晶體管或電容可以實(shí)現(xiàn)一個二進(jìn)制位,或0或1。

一個二進(jìn)制位包含的信息量稱為一 比特 。

從門電路到集成電路,從簡單到復(fù)雜的關(guān)鍵在于組合。

后面會提到,計算機(jī)中以8個位組合成一個字節(jié),做為基本的尋址單位,但也可以進(jìn)行位層面的計算,這就是位運(yùn)算。

4 字節(jié):存儲程序概念與尋址單位

計算機(jī)中以8個位組合成一個字節(jié),做為基本的尋址和運(yùn)算單位。不同的數(shù)據(jù)類型使用長度不同的內(nèi)存單元(字節(jié)數(shù)不同)。

在ASCII碼中,用一個字節(jié)來表示一個字符。不同的字符集的字符(如寬字符、多字符)需要不同數(shù)量的字節(jié)數(shù)。

5 字長:一次批量訪問和處理的字節(jié)數(shù)量

對于現(xiàn)在的電腦來時,其內(nèi)部實(shí)現(xiàn)都是串行操作的(可以利用電腦速度快和人類感官速度慢的特點(diǎn),通過快速切換的串行來模擬人類表面感覺的并行),單個訪問字節(jié)效果太低了,電腦可以一次訪問多個字節(jié),如32機(jī)就是一次可以訪問32個位,4個字節(jié),64機(jī)一次可以訪問8個字節(jié)。

一次性處理事務(wù)的一個固定長度的位(bit)的位數(shù)叫字長。計算機(jī)中大多數(shù)寄存器的大小是一個字長。計算機(jī)處理的典型數(shù)值(如int)也可能是以字長為單位。CPU和內(nèi)存之間的數(shù)據(jù)傳送單位也通常是一個字長。還有而內(nèi)存中用于指明一個存儲位置的地址也經(jīng)常是以字長為單位的?,F(xiàn)代計算機(jī)的字長通常為32、64位。內(nèi)部數(shù)據(jù)的表示或處理通常是字長的位數(shù)或分?jǐn)?shù)。

6 內(nèi)存對齊

考慮到計算機(jī)按字長處理數(shù)據(jù)的特點(diǎn),對于復(fù)合數(shù)據(jù)類型,如結(jié)構(gòu)體、類、共用體,都會考慮通過內(nèi)存對齊來提供數(shù)據(jù)操作(讀寫)效率。每個特定平臺上的編譯器都有自己的默認(rèn)“對齊系數(shù)”(也叫對齊模數(shù))。比如32位windows平臺下,VC默認(rèn)是按照8bytes對齊的(VC->Project->settings->c/c++->Code Generation中的truct member alignment 值默認(rèn)是8),程序員可以通過預(yù)編譯命令#pragma pack(n),n=1,2,4,8,16來改變這一系數(shù),其中的n就是你要指定的“對齊系數(shù)”。

編程基礎(chǔ)|漫淡數(shù)制、碼制、位、字節(jié)、字長及內(nèi)存對齊

內(nèi)存對齊規(guī)則:

1、數(shù)據(jù)成員對齊規(guī)則:結(jié)構(gòu)(struct)(或聯(lián)合(union)或類(class))的數(shù)據(jù)成員,第一個數(shù)據(jù)成員放在offset為0的地方,以后每個數(shù)據(jù)成員的對齊按照#pragma pack(n)指定的數(shù)值和這個數(shù)據(jù)成員自身長度中,比較小的那個進(jìn)行。

成員對齊系數(shù) = min(數(shù)據(jù)成員類型, n) = 4

2、結(jié)構(gòu)(或聯(lián)合)的整體對齊規(guī)則:在數(shù)據(jù)成員完成各自對齊之后,結(jié)構(gòu)(或聯(lián)合)本身也要進(jìn)行對齊(數(shù)據(jù)成員后的內(nèi)存單元是否需要填充),對齊將按照#pragma pack指定的數(shù)值和結(jié)構(gòu)(或聯(lián)合)最大數(shù)據(jù)成員長度中,比較小的那個進(jìn)行。

整體對齊系數(shù) = min((max(最大數(shù)據(jù)成員長度), 8) = 4

3、結(jié)合1、2推斷:當(dāng)#pragma pack的n值等于或超過所有數(shù)據(jù)成員長度的時候,這個n值的大小將不產(chǎn)生任何效果。

如果沒有通過pragma pack(m) 指定數(shù)值,VC規(guī)定各成員變量存放的起始地址相對于結(jié)構(gòu)的起始地址的偏移量必須為該變量的類型所占用的字節(jié)數(shù)的倍數(shù)

下面列出常用類型的對齊方式(vc6.0,32位系統(tǒng))。

類型 對齊方式(變量存放的起始地址相對于結(jié)構(gòu)的起始地址的偏移量)

Char 偏移量必須為sizeof(char)即1的倍數(shù)

Short 偏移量必須為sizeof(short)即2的倍數(shù)

int 偏移量必須為sizeof(int)即4的倍數(shù)

float 偏移量必須為sizeof(float)即4的倍數(shù)

double 偏移量必須為sizeof(double)即8的倍數(shù)

各成員變量在存放的時候根據(jù)在結(jié)構(gòu)中出現(xiàn)的順序依次申請空間,同時按照上面的對齊方式調(diào)整位置,空缺的字節(jié)VC會自動填充。同時VC為了確保結(jié)構(gòu)的大小為結(jié)構(gòu)的字節(jié)邊界數(shù)(即該結(jié)構(gòu)中占用最大空間的類型所占用的字節(jié)數(shù))的倍數(shù),所以在為最后一個成員變量申請空間后,還會根據(jù)需要自動填充空缺的字節(jié),也就是說:結(jié)構(gòu)體的總大小為結(jié)構(gòu)體最寬基本類型成員大小的整數(shù)倍,如有需要編譯器會在最末一個成員之后加上填充字節(jié)(trailing padding)。

例1:

struct Node1{double m1;char m2;int m3;};
編程基礎(chǔ)|漫淡數(shù)制、碼制、位、字節(jié)、字長及內(nèi)存對齊

為上面的結(jié)構(gòu)Node1分配空間的時候,VC根據(jù)成員變量出現(xiàn)的順序和對齊方式,

1 先為第一個成員m1分配空間,其起始地址跟結(jié)構(gòu)的起始地址相同(剛好偏移量0剛好為sizeof(double)的倍數(shù)),該成員變量占用sizeof(double)=8個字節(jié);

2 接下來為第二個成員m2分配空間,這時下一個可以分配的地址對于結(jié)構(gòu)的起始地址的偏移量為8,是sizeof(char)的倍數(shù),所以把m2存放在偏移量為8的地方滿足對齊方式,該成員變量占用 sizeof(char)=1個字節(jié);

3 接下來為第三個成員m3分配空間,這時下一個可以分配的地址對于結(jié)構(gòu)的起始地址的偏移量為9,不是sizeof (int)=4的倍數(shù),為了滿足對齊方式對偏移量的約束問題,VC自動填充3個字節(jié)(這三個字節(jié)沒有放什么東西);

4 最后要考慮整體對齊規(guī)則,這時下一個可以分配的地址對于結(jié)構(gòu)的起始地址的偏移量為12,剛好是sizeof(int), 由于8+4+4 = 16恰好是結(jié)構(gòu)體中最大空間類型double(8)的倍數(shù),所以sizeof(Node1) =16.

例2:

struct Node2{char a;int b;char c;};
編程基礎(chǔ)|漫淡數(shù)制、碼制、位、字節(jié)、字長及內(nèi)存對齊

再來分析一下Node2,

1 成員a占一個字節(jié),所以a放在了第1位的位置;

2 第二個變量b占4個字節(jié),為保證起始位置是4(sizeof(b))的倍數(shù),所以需要在a后面填充3個字節(jié),也就是b放在了從第5位到第8位的位置;

3 然后就是c放在了9的位置,此時4+4+1=9。

4 接下來考慮字節(jié)邊界數(shù),9并不是最大空間類型int(4)的倍數(shù),應(yīng)該取大于9且是4的的最小整數(shù)12,所以sizeof(Node2) = 12.

例3:

typedef struct{char a;char b;int c;}Node3;
編程基礎(chǔ)|漫淡數(shù)制、碼制、位、字節(jié)、字長及內(nèi)存對齊

同樣的方法我們要計算出sizeof(Node3) = 8;

例4:

struct node4 {char c1;Node3 n3;char c2};
編程基礎(chǔ)|漫淡數(shù)制、碼制、位、字節(jié)、字長及內(nèi)存對齊

n3的最寬簡單成員的類型為int,n3在考慮最寬簡單類型成員時是將Node3“打散”看的,所以n3的最寬簡單類型為int,這樣,通過n3定義的變量,其存儲空間首地址需要被4整除,整個sizeof(n3)的值也應(yīng)該被4整除。

1 c1的偏移量為0;

2 n3的偏移量呢?這時n3是一個整體,它作為結(jié)構(gòu)體變量也滿足前面三個準(zhǔn)則,所以其大小為8,偏移量為4,c1與n3之間便需要3個填充字節(jié);

3 而c2與n3之間就不需要了,所以c2的偏移量為12;

4 考慮整體偏移,算上c2的大小為13,13是不能被4整除的,這樣末尾還得補(bǔ)上3個填充字節(jié)。最后得到sizeof(S3)的值為16。

通過上面的敘述,我們可以得到一個公式:

結(jié)構(gòu)體的大小等于最后一個成員的偏移量加上其大小再加上末尾的填充字節(jié)數(shù)目,即:

sizeof( struct ) = offsetof( last item ) + sizeof( last item ) + sizeof( trailing padding )

再來實(shí)一個整體實(shí)例:

#include <iostream>using namespace std;//預(yù)編譯命令#pragma pack(n),n=1,2,4,8,16來改變這一系數(shù),其中的n就是你要指定的“對齊系數(shù)”。#pragma pack(8)typedef struct people{	double weight; 	char sex; // 8 + 1 	short age; // 9 + 1+2	int money; // 12 + 4	char flag; // 16 + 1 + 7	}strtSize;//}__attribute__((packed)) strtSize;/讓GCC編譯器取消結(jié)構(gòu)在編譯過程中的優(yōu)化對齊void main(){	cout<<sizeof(double)<<endl; // 8	cout<<sizeof(strtSize)<<endl; // 24}

-End-

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多