數據模型(LP32 ILP32 LP64 LLP64 ILP64 )
32位環境涉及"ILP32"數據模型,是因為C數據類型為32位的int、long、指針。而64位環境使用不同的數據模型,此時的long和指針已為64位,故稱作"LP64"數據模型。
現今所有64位的類Unix平台均使用LP64數據模型,而64位Windows使用LLP64數據模型,除了指針是64位,其他基本類型都沒有變。
| Data Type | ILP32 | LP32 | ILP64 | LP64 | LLP64 |
| 宏定義 | _ | _ | _ | __LP64__ | __LLP64__ |
| 平台 | Win32 API / Unix 和 Unix 類的系統 (Linux,Mac OS X) | Win16 API | Unix 和 Unix 類的系統 (Linux,Mac OS X) | Win64 API | |
| char | 8 | 8 | 8 | 8 | 8 |
| short | 16 | 16 | 16 | 16 | 16 |
| int | 32 | 32 | 64 | 32 | 32 |
| long | 32 | 32 | 64 | 64 | 32 |
| long long | 64 | 64 | 64 | 64 | 64 |
| pointer | 32 | 32 | 64 | 64 | 64 |
在這張表中,LP64,ILP64,LLP64是64位平台上的字長模型,ILP32和LP32是32位平台上的字長模型。
LP64意思是long和pointer是64位,
ILP64指int,long,pointer是64位,
LLP64指long long和pointer是64-bit的。
ILP32指int,long和pointer是32位的,
LP32指long和pointer是32位的。
float 都是4字節;
double 都是8字節;(C中直接寫小數,默認是double型)
這 3 個 64 位模型(LP64、LLP64 和 ILP64)之間的區別在於非浮點數據類型。當一個或多個 C 數據類型的寬度從一種模型變換成另外一種模型時,應用程序可能會受到很多方面的影響。這些影響主要可以分為兩類:
- 數據對象的大小。編譯器按照自然邊界對數據類型進行對齊;換而言之,32 位的數據類型在 64 位系統上要按照 32 位邊界進行對齊,而 64 位的數據類型在 64 位系統上則要按照 64 位邊界進行對齊。這意味着諸如結構或聯合之類的數據對象的大小在 32 位和 64 位系統上是不同的。
- 基本數據類型的大小。通常關於基本數據類型之間關系的假設在 64 位數據模型上都已經無效了。依賴於這些關系的應用程序在 64 位平台上編譯也會失敗。例如,
sizeof (int) = sizeof (long) = sizeof (pointer)的假設對於 ILP32 數據模型有效,但是對於其他數據模型就無效了。
總之,編譯器要按照自然邊界對數據類型進行對齊,這意味着編譯器會進行 “填充”,從而強制進行這種方式的對齊,就像是在 C 結構和聯合中所做的一樣。結構或聯合的成員是根據最寬的成員進行對齊的。
數據類型轉換原則

結構體對齊,默認對齊原則:
1.數據類型對齊值:
char型數據自身對齊值為1
short為2,int、float為4,double為8(windows)
解釋:
char變量只要有一個空余的字節即可存放
short要求首地址能被2整除
int、float、double同理
2.結構體的對齊值:
其成員中自身對齊值最大的那個值。
解釋:
結構體最終對齊按照數據成員中最長的類型的整數倍
指定對齊原則:
使用#pragma pack改變默認對其原則
格式:
#pragma pack (value)時的指定對齊值value。
結構體最終對齊按照指定對齊值的整數倍
注意:
1.value只能是:1 2 4 8等
2.指定對齊值與數據類型對齊值相比取較小值
如:如果指定對齊值:
設為1:則short、int、float等均為1
設為2:則char仍為1,short為2,int 變為2
移位運算
左移<<
將一個數的二進制位左移,高位丟棄,低位補0
例:a = a<<2 將a的二進制數左移2位,右補0
若a=15,即二進制數0 0 0 01111
左移2位得0 011110 0,(十進制數60)
>>算術右移
有符號數,如果為正數,則左邊移入0,右邊丟棄
如果為負數,左邊移入1,右邊丟棄
>>邏輯右移
不關心正數、負數,左邊均移入0,右邊丟棄
算術或者邏輯右移,由編譯器決定
博主今天在寫代碼的時候遇到一個奇怪的問題,程序的要求是實現一個int的移位操作,不管左移還是右移,空出來的位置通通置0即邏輯移位。一開始沒注意太多直接用了<<和>>移位操作符,結果卻發現實現是錯誤的==!
經過查證發現,c語言中的移位操作符,在左移時執行的是邏輯移位,在右移時執行的是算術移位。那怎么用>>實現右移操作呢?
又經過查證得知,無符號數的移位操作都是執行的邏輯移位。那么要想用>>實現邏輯右移就可以將操作數強制類型轉化為unsigned類型,如下:
int a = 0xfffffffe;
int b = (unsigned int)a >> 1;
執行的結果是2147483647即7fffffff,可見其右移后左端補的是0。
綜上:C語言中移位操作符實現的是邏輯左移和算術右移,但是算術左移和邏輯左移的效果相同,算術右移和邏輯右移的效果不同,要實現邏輯右移可將操作數強制類型轉化為無符號數
