深入理解計算機系統筆記二

   對於自動駕駛,特別是嵌入式開發板上移植程序來說,用某個確定大小的表示來編碼數據類型非常重要。例如,當編寫程序,使得機器能夠按照一個標準協議在因特網上通信時,讓數據類型與協議指定的數據類型兼容是非常重要的。不過現在64位系統已經比較普及,不像以前處於過渡階段。特別是long型,在不同的機器上有不同的取值範圍,而實際上C語言標準只指定了每種數據類型的最小範圍,而不是確定的範圍。雖然我們可以選擇與大多數機器上的標準表示兼容的數據類型,但是這也不能保證可移植性。

    從32位到64位,根本性的區別在於兩種數據類型發生了變化:long和pointer。在32位環境下,兩者長度都是32位,也就是4個字節;而在64位環境下都是8個字節。所以當你把pointer或者long型數據賦給int型時,會發生數據截斷(data truncation)。32位應用的數據模型我們稱作ILP32(之所以這樣命名,是因爲int,long,pointer都是32位),而64位應用則採用LP64模型(意味着long,pointer變成64位了,其他的不變)。在當前的32位環境下,我們可以認爲int,long,pointer是等價的,因爲它們佔用相同的字節,於是就有很多混用的情況;但是到了64位的時代,long和Poniter的大小都改變了,原來的假設不再成立。

1.1int和pointer轉換問題

因爲integer與pointer大小相同,所以32位代碼中常常把pointer轉換爲int或者unsigned int,以便算術運算。爲了移植,你可以把pointer轉換爲unsigned long,因爲long和pointer都是等長的,無論是在ILP32或LP64。但是,爲了使代碼更清晰,推薦用uintptr_t,uintptr_t和intptr_t都需要包含頭文件inttypes.h。
例如:下面代碼在64位環境下編譯出錯:

char *p = &something;
p = (char *) ((int)p & PAGEOFFSET);
 
% cc ..
warning: conversion of pointer loses bits

改用uintptr_t後,無論是32位或者64位都沒問題:

char *p = &something;
p = (char *) ((uintptr_t)p & PAGEOFFSET);

1.2 int和long轉換

int A = 0;
long B = 0;
long C = 0;
...
A = B + C;
 
 
% cc
warning: assignment of 64-bit integer to 32-bit integer

1.3 結構體字節對齊及大小問題

這個問題我是切切實實吃個虧的,特別要注意結構體中有long類型的(無人車系統裏各個傳感器數據包中的時間戳unsigned long long)

struct T 
{
int i; 
long j; 
int k; 
char *p;
};

這個時候需要注意結構體中不同數據類型的位置排布

struct T
{
char *p;
long j;
int i;
int k;
};

此時,無需擴展,sizeof(T)=8+8+4+4=24.

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章