青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆 - 74, 文章 - 0, 評論 - 26, 引用 - 0
數據加載中……

新時代的門前 32位世界中的64位編程

為16、32、64位架構編寫可移植代碼

  與16位相比,32位意味著程序更快、可直接尋址訪問更多的內存和更好的處理器架構。鑒于此,越來越多的程序員已經開始考慮利用64位處理器所帶來的巨大優勢了。

  克雷研究(Cray Research 應為品牌名)計算機已經開始使用64位字,并可訪問更大的內存地址。然而,作為正在向開發標準軟件和與其他操作系統相互努力的一部分,我們已經停止了移植那些原本基于32位處理器的代碼。事實上,我們不斷遇到我們稱之為“32位主義”的代碼,這些代碼都是在假定機器字長為32位的情況下編寫的,因而很難移植這種代碼,所以必須確立一些簡單的指導方針,以便助于編寫跨16、32、64位處理器平臺的代碼。

  由于有一些遺留問題,C語言在數據類型和數據構造方面,顯得有點過剩了。可以使用的不僅僅是char、short、int和long類型,還有相應的unsigned(無符號)類型,當然你可在結構(structure)和聯合(union)中混合使用,可以在聯合中包含結構,再在結構中包含聯合,如果還嫌數據類型不夠復雜,還可以轉換成比特位,當然也可以把一種數據類型轉換成另一種你想要的數據類型。正是因為這些工具太強大,如果不安全地使用它們,就有可能會傷到自己了。

  高級代碼的高級結構

  在Kernighan和Plauger經典的《The Elements of Programming Style》一書中,他們的建議是“選擇使程序看上去簡單的數據表示法”。對個人而言,這意味著為高級編程使用高級數據結構,而低級編程使用低級數據結構。

  在我們移植的程序中,有一個常見的32位主義bug,不如拿它來做個例子,科內爾大學編寫的用于網間互訪的路由協議引擎,在伯克利網絡環境下(指TCP/IP),自然是使用inet_addr( )來把表示Internet地址的字符串轉換成二進制形式。Internet地址碰巧也是32位的,就如運行伯克利網絡系統的其他計算機一樣,都是有著同樣的字寬。

  但也存在著有關Internet地址的高級定義:in_ addr結構。這個結構定義包括了子域s_ addr,它是一個包含了Internet地址的unsigned long標量。inet_addr()接受一個指向字符的指針,并且返回一個unsigned long,在轉換地址字符串過程中如果發生錯誤,inet_addr將返回-1。

  程序Gated讀取以文本格式存放Internet地址的配置文件,并把它們放入sockaddr_in(這是一個包含了結構in_addr的高級結構)。例1(a)中的代碼可以在32位電腦上正常運行,但移植到克雷研究計算機上,卻無法運行,為什么呢?

  例1:高級代碼的高級結構

  (a)

struct sockaddr_in saddrin
char *str;

if ((saddrin.sin_addr.s_addr = inet_addr(str)) == (unsigned long)-1) {
 do_some_error_handling;
}

  (b)

struct sockaddr_in saddrin
char *str;

if (inet_aton(str, &saddrin.sin_addr) ! = OK) {
 do_some_error_handling;
}

  因為只要inet_addr能夠正確地解析字符串,那么一切OK。當inet_addr在64位計算機上返回一個錯誤時,這段代碼卻未能捕捉到。你必須要考慮比較語句中的數據位寬,來確定到底是哪出了錯。

  首先,inet_addr返回錯誤值——unsigned long -1,在64位中表示為比特位全為1,這個值被存儲在結構in_addr下的子域s_addr中,而in_addr必須是32位來匹配Internet地址,所以它是一個32比特位的unsigned int(在我們的編譯器上,int是64位)。現在我們存儲進32個1,存儲進的值將與unsigned long -1比較。當我們存儲32個1于unsigned int時,編譯器自動把32位提升為64位;這樣,數值0x00000000 ffffffff與0xffffffff ffffffff的比較當然就失敗了。這是一個很難發現的bug,特別是在這種因為32位到64位的隱式提升上。

  那我們對這個bug怎么辦呢?一個解決方法是在語句中比較0xffffffff,而不是-1,但這又會使代碼更加依賴于特定大小的對象。另一個方法是,使用一個中間的unsigned long變量,從而在把結果存入sockaddr_in前,執行比較,但這會讓程序代碼更復雜。

  真正的問題所在是,我們期望一個unsigned long值與一個32位量(如Internet地址)相等。Internet地址必須以32位形式進行存儲,但有些時候用一個標量,來訪問這個地址的一部分,是非常方便的。在32位字長的電腦中,用一個long數值(常被當作32位)來訪問這個地址,看上去沒什么問題。讓我們暫時不想一個低級的數據項(32位Internet地址)是否與一個機器字相等,那么高級數據類型結構in_addr就應該被一直使用。因為in_addr中沒有無效值,那么應有一個單獨的狀態用作返回值。

  解決方案是定義一個新的函數,就像inet_addr那樣,但返回一個狀態值,而且接受一個結構in_addr作為參數,參見例1(b)。因為高級的數據元素可以一直使用,而返回的值是沒有溢出的,所以這個代碼是可以跨架構移植的,而不管字長是多少。雖然伯克利發布了NET2,其中的確定義了一個新的函數inet_aton(),但如果試著改變inet_addr()中的代碼,將會損壞許多程序。

  低級代碼的低級結構

  低級編程意味著直接操縱物理設備或者特定協議的通訊格式,例如,設備驅動程序經常使用非常精確的位模式來操縱控制寄存器。此外,網絡協議通過特定的比特位模式傳輸數據項時,也必須適當地轉譯。

  為了操縱物理數據項,此處的數據結構必須準確地反映被操縱的內容。比特位是一個不錯的選擇,因為它們正好指定了比特的位數及排列。事實上,正是這種精確度,使比特位相對于short、int、long,更好地映像了物理結構(short、int、long會因為電腦的不同而改變,而比特位不會)。

  當映像一個物理結構時,是通過定義格式來使比特位達到這種精度的,這就使你必須一直使用一種編碼風格來訪問結構。此時的每個位域都是命名的,你寫出的代碼可直接訪問這些位域。當訪問物理結構時,有件事可能你并不想去做,那就是使用標量數組(short、int、or long),訪問這些數組的代碼都假定存在一個特定的比特位寬,當移植這些代碼到一臺使用不同字寬的電腦上時,就可能不正確了。

  在我們移植PEX圖像庫時遇到的一個問題,就涉及到其映像的協議消息結構。在某臺電腦上,如果int整型的長度與消息中的元素一樣,那例2(a)中的代碼就會工作得很正常。32位的數據元素在32字長的電腦上沒有問題,拿到64位的克雷計算機上,它就出錯了。對例2(b)而言,不單要改變結構定義,還要改變所有涉及到coord數組的代碼。這樣,擺在我們面前就有兩個選擇,要么重寫涉及此消息的所有代碼,要么定義一個低級的結構和一個高級的結構,然后用一段特殊的代碼把數據從一個拷貝到另一個當中,不過我也不期望可以找出每個對zcoord = draw_ msg.coord[2]的引用,而且,當現在需要移植到一個新架構上時,把所有的代碼都改寫成如例2(c)所示無疑是一項艱苦的工作。這個特殊的問題是由于忽視字長的不同而帶來的,所以不能假設在可移植的代碼中機器字長、short、int、long都是具有同樣的大小。

  例2:低級代碼的低級結構

  (a)

struct draw_msg {
 int objectid;
 int coord[3];
}

  (b)

struct draw_msg {
 int objectid:32;
 int coord1:32;
 int coord2:32;
 int coord3:32;
}

  (c)

int *iptr, *optr, *limit;
int xyz[3];

iptr = draw_msg.coord;
limit = draw_msg.coord + sizeof(draw_msg.coord);

optr = xyz;
while (iptr < limit)
*optr++ = *iptr++;
結構打包和字對齊

   正是因為編譯器會對結構進行打包,所以不同計算機上字長的變化,還導致了另一個問題。C編譯器在字(word)的邊界上對齊字長,當具有一個字長的數據后面緊接著一個較小的數據時,這種方法會產生內存空缺(不過也有例外,比如說當有足夠多的小數據剛好可以填充一個字時)。

   一些聰明的程序員在聲明聯合時,往往在其中會帶有兩個或更多的結構,其中一個結構剛好填充聯合,另一個則可以用來從不同的角度來看待這個聯合,參見例3(a)。假設這段代碼是為16位字長的計算機所寫,int為16位,long為32位,那么存取這個結構的代碼將會得到正常的映射關系(如圖1),而例3(b)中的代碼也會按預期的那樣工作。可是,如果這段代碼一旦移植到另一臺具有32位字長的計算機上時,映射關系就改變了。如果新計算機上的編譯器允許你使用16位的int,那么字的對齊就會像圖2所示了,或者如果編譯器遵循K&R約定,那么int將會和一個字(32比特)一樣長,對齊就如圖3所示,在任一情況下,這都將導致問題。




  例3:結構打包和字對齊

  (a)

union parse_hdr {
 struct hdr {
  char data1;
  char data2;
  int data3;
  int data4;
} hdr;
struct tkn {
 int class;
 long tag;
} tkn;
} parse_item;

  (b)

char *ptr = msgbuf;

parse_item.hdr.data1 = *ptr++;
parse_item.hdr.data2 = *ptr++;
parse_item.hdr.data3 = (*ptr++ << 8 | *ptr++);
parse_item.hdr.data4 = (*ptr++ << 8 | *ptr++);

if (parse.tkn.class >= MIN_TOKEN_CLASS && parse.tkn.class <= MAX_TOKEN_CLASS) {
 interpret_tag(parse.tkn.tag);
}

  在第一個情況中(圖2),tag域不是像期望的那樣線性拉長,而被填充了一些垃圾。而在第二個情況中(圖3),無論是class還是tag域,都不再有意義,兩個char值因為被打包成一個int,所以也都不再正確。再次強調,首先不要假設標準數據類型大小一樣,其次還要了解它們是怎樣被映射成其他數據類型的,這才是書寫可移植代碼的最好方法。

  機器尋址特性

  幾乎所有的處理器都在字邊界上以字為單位進行尋址,而且通常都為此作了一些優化。另有一些的處理器允許其他類型的尋址,如以字節為單位尋址、或在半個字邊界上以半字為單位尋址,甚至還有一些處理器有輔助硬件允許在奇數邊界上同時以字和半字進行尋址。

  尋址機制在不同計算機上會有所變化,最快的尋址模式是在字邊界上以字為單位進行尋址。其他方式的尋址需要輔助硬件,通常都會對內存訪問增加了一些時鐘周期。而這些過多的模式和特殊硬件的支持,是與RISC處理器的設計初衷背道而馳的,就拿克雷計算機來說,就只支持在字邊界上以字為單位進行尋址。

  在那些不提供多種數據類型尋址方式的計算機上,編譯器可以提供一些模擬。例如:編譯器可以生成一些指令,當讀取一個字時,通過移位和屏蔽,來找到所想要的位置,以此來模擬在字中的半字尋址,但這會需要額外的時鐘周期,并且代碼體積會更大。

  從這點上來說,位域的效率是非常低的,在以位域來取出一個字時,它們產生的代碼體積最大。當你存取同一個字中的其他位域時,又需要對包含這個位域字的內存,重新進行一遍尋址,這就是典型的以空間換時間。

  當在設計數據結構時,我們總是想用可以保存數據的最小數據類型,來達到節省空間的目的。我們有時小氣得經常使用char和short,來存取位特域,這就像是為了節省一角錢,而花了一元錢。儲存空間上的高效,會付出在程序速度和體積上隱藏的代價。

  試想你只為一個緊湊結構分配了一小點的空間,但卻產生了大量的代碼來存取結構中的域,而且這段代碼還是經常執行的,那么,會因為非字尋址,而導致代碼運行緩慢,而且充斥了大量用于提取域的代碼,程序體積也因此增大。這些額外代碼所占的空間,會讓你前面為節省空間所做的努力付之東流。

  在高級數據結構中,特定的比特定位已不是必須的了,應在所有的域中都使用字(word),而不要操心它們所占用的空間。特別是在程序某些依賴于機器的部分,應該為字準備一個typedef,如下:

/*在這臺計算機上,int是一個字長*/
typedef word int;

  在高級結構中,對所有域都使用字有如下好處:

  a.. 對其他計算機架構的可移植性

  b.. 編譯器可能生成最快的代碼

  c.. 處理器可能最快地訪問到所需內存

  d.. 絕對沒有結構對齊的意外發生

  必須也承認,在某些時候,是不能做到全部使用字的。例如,有一個很大的結構,但不會被經常存取,如果使用了數千個字的話,體積將會增大25%,但使用字通常會節省空間、提高執行速度,而且更具移植性。

  以下是我們的結論:

  書寫跨平臺移植的代碼,其實是件簡單的事情。最基本的規則是,盡可能地隱藏機器字長的細節,用非常精確的數據元素位大小來映射物理數據結構。或者像前面所建議的,為高級編程使用高級數據結構,而低級編程使用低級數據結構,當闡明高級數據結構時,對標準C的標量類型,不要作任何假設

posted on 2006-07-07 13:51 井泉 閱讀(302) 評論(0)  編輯 收藏 引用 所屬分類: c軟件工程

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产精品亚洲激情| 欧美国产激情| 亚洲欧洲久久| 亚洲国产精品国自产拍av秋霞 | 久久女同精品一区二区| 午夜亚洲福利| 老司机免费视频一区二区| 蜜桃久久精品一区二区| 亚洲国产精品va在线看黑人| 欧美在线影院在线视频| 蜜乳av另类精品一区二区| 欧美高清在线| 亚洲特色特黄| 久久精品中文字幕免费mv| 欧美a级一区| 国产精品一级| 亚洲精品国产精品乱码不99 | 亚洲一级在线| 久久久久www| 亚洲激情av在线| 午夜精品视频| 欧美日韩国产色综合一二三四| 国产精品久久久久999| 好男人免费精品视频| 一区二区日韩| 欧美日韩国产精品一卡| 免费观看成人| 亚洲欧美资源在线| 亚洲视频一区在线| 午夜精品久久久久久99热软件| 欧美一区二区三区播放老司机| 久久这里只精品最新地址| 亚洲乱码国产乱码精品精98午夜| 欧美亚洲日本一区| 欧美日韩日本国产亚洲在线| 国产综合一区二区| 亚洲香蕉成视频在线观看 | 亚洲午夜精品久久| 久久夜色精品国产欧美乱| a4yy欧美一区二区三区| 久久99在线观看| 国产精品毛片va一区二区三区| 亚洲激情不卡| 久久久久久精| 香港久久久电影| 欧美日韩免费在线观看| 亚洲精品一二| 亚洲国产午夜| 久久久久在线观看| 国产专区一区| 久久精品一区蜜桃臀影院| 在线中文字幕一区| 欧美偷拍一区二区| 99综合在线| 亚洲精品久久久久久久久久久久 | 欧美国产免费| 美女国内精品自产拍在线播放| 国产视频欧美| 久久激情五月激情| 香蕉国产精品偷在线观看不卡 | 国产麻豆一精品一av一免费| 亚洲自拍偷拍视频| 亚洲综合第一| 国产自产2019最新不卡| 久久久噜噜噜久久| 久久久伊人欧美| 最近看过的日韩成人| 亚洲国产日韩一区二区| 欧美激情1区| 亚洲视频在线观看| 亚洲欧美伊人| 一区视频在线播放| 亚洲电影自拍| 国产精品video| 欧美一区二区三区在线观看视频| 久久欧美中文字幕| 美日韩精品视频免费看| 久久夜色精品国产亚洲aⅴ| 尤物九九久久国产精品的特点| 久久资源av| 欧美丰满少妇xxxbbb| 一区二区毛片| 午夜精品亚洲一区二区三区嫩草| 国产美女扒开尿口久久久| 久久精品视频在线观看| 久久全国免费视频| 亚洲调教视频在线观看| 午夜精品成人在线| 亚洲国产日韩欧美一区二区三区| 亚洲国产婷婷香蕉久久久久久| 欧美婷婷久久| 久色婷婷小香蕉久久| 欧美绝品在线观看成人午夜影视| 亚洲欧美日韩中文视频| 久久久之久亚州精品露出| 9久草视频在线视频精品| 亚洲免费影院| 亚洲精品偷拍| 午夜精品亚洲| 亚洲一区二区三区在线观看视频| 久久成人18免费观看| 艳妇臀荡乳欲伦亚洲一区| 亚洲综合视频一区| 99精品视频免费在线观看| 午夜欧美大尺度福利影院在线看| 亚洲欧洲日产国产综合网| 亚洲一区欧美一区| 日韩视频在线观看| 久久九九精品| 欧美一区日本一区韩国一区| 欧美国产日韩一区二区三区| 欧美专区在线播放| 欧美视频中文字幕| 欧美激情在线观看| 伊人色综合久久天天五月婷| 亚洲私人影院| 一区二区三区四区国产精品| 久久另类ts人妖一区二区| 欧美亚洲视频在线观看| 欧美日韩精品一区二区天天拍小说| 老妇喷水一区二区三区| 国产欧美另类| 亚洲香蕉成视频在线观看| 99国产精品久久久久久久成人热 | 午夜激情一区| 亚洲免费中文| 欧美视频日韩视频在线观看| 亚洲国产一区二区视频| 亚洲电影免费在线| 久久精品91久久久久久再现| 欧美与黑人午夜性猛交久久久| 国产精品成人v| 一区二区三区四区国产| 一区二区三区免费观看| 欧美精品情趣视频| 91久久国产精品91久久性色| 91久久精品国产91性色tv| 久久精品理论片| 免费日韩av电影| 亚洲激情婷婷| 欧美极品影院| 99精品热视频只有精品10| 欧美α欧美αv大片| 欧美国产大片| 亚洲看片免费| 欧美精选一区| 在线视频亚洲| 欧美在线视频日韩| 狠狠色丁香婷婷综合| 久久综合国产精品| 亚洲国产一区二区在线| 亚洲小视频在线观看| 国产精品美女久久久久久久| 午夜精品999| 欧美好吊妞视频| 亚洲神马久久| 国产亚洲精品久久久久久| 久久蜜桃资源一区二区老牛| 亚洲第一黄网| 亚洲欧美精品在线观看| 国产一区欧美| 欧美女同在线视频| 亚洲欧美精品| 欧美激情亚洲| 午夜精品久久久久久99热| 加勒比av一区二区| 欧美日韩另类视频| 欧美一级艳片视频免费观看| 欧美激情二区三区| 亚洲欧美变态国产另类| 激情久久久久久久| 欧美日韩视频在线一区二区| 欧美一区二区三区免费观看视频| 免费日韩av片| 性做久久久久久久久| 亚洲福利视频一区| 国产精品免费区二区三区观看| 久久久久久久久伊人| 99视频热这里只有精品免费| 久久精品免视看| 一区二区三区国产在线观看| 国产三区精品| 欧美日韩亚洲一区二区三区在线观看| 亚洲欧美日韩国产中文 | 亚洲欧美久久久| 亚洲精品免费在线| 国产一区二区中文| 欧美国产日韩精品| 久久久精品国产一区二区三区| 99精品久久| 欧美激情一级片一区二区| 欧美中文字幕在线播放| 亚洲一区在线视频| 亚洲国产91色在线| 国产视频丨精品|在线观看| 欧美午夜视频一区二区| 欧美波霸影院| 裸体丰满少妇做受久久99精品| 亚洲欧美日韩网| 中文日韩在线视频|