日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網營銷解決方案
32位程序和64位程序這些區(qū)別你知道嗎?

本文轉載自微信公眾號「 編程珠璣」,轉載本文請聯(lián)系 編程珠璣公眾號。

建網站原本是網站策劃師、網絡程序員、網頁設計師等,應用各種網絡程序開發(fā)技術和網頁設計技術配合操作的協(xié)同工作。成都創(chuàng)新互聯(lián)專業(yè)提供網站設計制作、成都網站建設,網頁設計,網站制作(企業(yè)站、響應式網站開發(fā)、電商門戶網站)等服務,從網站深度策劃、搜索引擎友好度優(yōu)化到用戶體驗的提升,我們力求做到極致!

作者:守望,linux應用開發(fā)者,目前在公眾號【編程珠璣】 分享Linux/C/C++/數據結構與算法/工具等原創(chuàng)技術文章和學習資源。

我們在編寫C/C++程序時,32位程序和64位程序的代碼有何區(qū)別?如何編寫既可以編譯成32位程序又可以編譯成64位程序的代碼?

代碼上的區(qū)別

實際上,對于32位程序和64位程序來說,代碼上的區(qū)別不大,嚴格來說,甚至是一樣的,它的主要區(qū)別在于一些基本數據類型占用的字節(jié)長度不一樣(注:這里僅針對類Unix平臺)

類型 32位占用字節(jié) 64位占用字節(jié)
long48
unsigned long48
指針48

當然這里的long包括一些用它定義的類型,如time_t,它的長度也是有區(qū)別的,關于time_t,還有一個有意思的問題《什么是2038問題》。

除此之外,其默認對齊字節(jié)數,也不一樣,32位程序為4字節(jié),64位程序默認為8字節(jié)。關于字節(jié)對齊,可參考《理一理字節(jié)對齊的那些事》。

可執(zhí)行文件上的區(qū)別

來看個小例子吧,看看他們有何區(qū)別。

 
 
 
  1. //來源:公眾號編程珠璣 
  2. //作者:守望先生 
  3. test.c 
  4. #include 
  5. struct Test 
  6.   int a; 
  7.   long b; 
  8. }; 
  9. int main(void) 
  10.     printf("sizeof(long) = %zu\n",sizeof(long)); //long類型占用字節(jié)數 
  11.     printf("sizeof(unsigned long) = %zu\n",sizeof(unsigned long));//unsigned long類型占用字節(jié)數 
  12.     struct Test test = {1,2}; 
  13.     printf("sizeof(struct Test) = %zu\n",sizeof(test));//用于測試對齊字節(jié)數 
  14.     printf("sizeof(pointer) = %zu\n",sizeof(&test)); //指針占用字節(jié)數 
  15.     return 0; 

如果你的系統(tǒng)是64位,默認編譯為64位程序,而如果需要編譯為32位程序,則需要帶上-m32參數,如果你的系統(tǒng)是32位的,那么是不能直接運行64位程序的,但是如果是64位的,是可以運行32位程序的。(實際上你在下載軟件的時候需要選擇位數的時候,就需要注意了,如果你的系統(tǒng)32位的, 但是你下載了一個64位的程序包,自然是不可用的,但是反過來卻可以。)

編譯為32位程序運行:

 
 
 
  1. $ gcc -o  test32 test.c -m32 
  2. $ ./test32 
  3. sizeof(long) = 4 
  4. sizeof(unsigned long) = 4 
  5. sizeof(struct Test) = 8 
  6. sizeof(pointer) = 4 

編譯位64位程序運行:

 
 
 
  1. $ gcc -o test64 test.c  
  2. $ ./test64  
  3. sizeof(long) = 8 
  4. sizeof(unsigned long) = 8 
  5. sizeof(struct Test) = 16 
  6. sizeof(pointer) = 8 

通過運行結果,我們也可以看出前面提到的差別。

那么可執(zhí)行文件本身有什么差別呢?

 
 
 
  1. $ readelf -h test32 
  2. ELF Header: 
  3.   Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00  
  4.   Class:                             ELF32 
  5.   Data:                              2's complement, little endian 
  6.   Version:                           1 (current) 
  7.   OS/ABI:                            UNIX - System V 
  8.   ABI Version:                       0 
  9.   Type:                              EXEC (Executable file) 
  10.   Machine:                           Intel 80386 
  11.   (...) 

可以看到Class屬性標識為ELF32。

而對于64位:

 
 
 
  1. readelf -h test64 
  2. ELF Header: 
  3.   Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00  
  4.   Class:                             ELF64 
  5.   Data:                              2's complement, little endian 
  6.   Version:                           1 (current) 
  7.   OS/ABI:                            UNIX - System V 
  8.   ABI Version:                       0 
  9.   Type:                              EXEC (Executable file) 
  10.   Machine:                           Advanced Micro Devices X86-64 

它的屬性為ELF64。實際上我們可以通過readelf發(fā)現很多信息。

例如你在進行交叉編譯后出現鏈接錯誤或者最后的執(zhí)行程序在目標機器無法運行,則可以查看Machine部分,看看程序是否能在你想要的平臺運行。

例如64位程序中的Machine中顯示的是Advanced Micro Devices X86-64,至少說明它在arm平臺是沒法正常運行的。

一個程序最大能申請多少內存空間?

還記得這道面試題嗎?如果你只是回答Linux理論最大不超過3G,windows不超過G,那肯定是不完整的,這里必須要區(qū)分32位程序和64位程序。

這一點在《解引用NULL為什么會掛死?》中已經有所提及。32位決定了其虛擬地址空間的最大值為2^32,即4G,除去操作系統(tǒng)占用的1G左右,剩下3G左右,當然了這里面3G包含了所有代碼,數據等,總結就是,最終能使用的不超過3G。不到3G的地址空間。(注這里并不表示它只能訪問計算機4G的內存,而是表示最大尋址范圍為4G)。那么64位的虛擬地址空間擴展到了17179869184G,所以,看出差別了嗎?

通過上面簡單的分析可以發(fā)現,64位程序理論能使用的內存是驚人的,而32位程序卻非常有限,除此之外,還有一個在《什么是2038問題》》中提到的問題,就是2038年后,32位程序將很難正常使用時間相關的處理。

當然了,64位系統(tǒng)通常能夠支持更高精度的浮點運算。

同時支持32位和64位代碼編寫原則

基于前面提到的原因,很多傳統(tǒng)系統(tǒng)都開始著手移植到64位系統(tǒng)上,而如果原先代碼就非常規(guī)范的話,移植工作還算比較輕松,鏈接64位庫,編譯成64位程序即可,但是如果沒有遵循以下原則,那么工作量就比較大了:

依賴long類型和指針類型占用空間大小以及其表示范圍

當然,對于這個原則,其表現可能非常多。

long和int混用

例如:

 
 
 
  1. void test(long len) 
  2.     int localLen = len; 
  3.     xxxx; 

這里很明顯可能會發(fā)現截斷。最常見的就是:

 
 
 
  1. int len = sizeof(xxx); 

當然,這里大多數情況下也不會有太大問題,直到其長度大于int表示范圍。

慎用掩碼定義

我們可能經常需要定義一些掩碼:

 
 
 
  1. long mask = OxFFFFFFFFL; 

在 32 位系統(tǒng)上,這會將所有位都置位(每位全為 1),但是在 64 位系統(tǒng)上,只有低 32 位被置位了。結果是這個值是 0x00000000FFFFFFFF。

如果希望所有位置1,那么可以:

 
 
 
  1. long mask = 1L << ((sizeof(long) * 8) - 1); 

打印指針

32下,這樣的沒問題的:

 
 
 
  1. int a = 10; 
  2. int *p = &a; 
  3. printf("%x",p); 

但是64位下,打印不完全。自然要使用:

 
 
 
  1. printf("%p",p); 

傳送結構體數據

在32位和64位系統(tǒng)中,其默認對齊字節(jié)數是不一樣的。

 
 
 
  1. strcut test 
  2.     int a; 
  3.     long b; 

如果對方是64位,發(fā)送過來上述結構體數據,而你的是32位程序,可想而知,結果并不會如你所愿。前面占用空間16字節(jié),而后者占用空間8字節(jié)。

顯示定義long

如果你的數據類型是long,那么可以使用L顯示說明:

 
 
 
  1. long i = 1 << a; 

上面的寫法建議換成:

 
 
 
  1. long i  = 1L << a; 

避免數據被截斷。

總結

關于這樣的點還有很多,這里不一一介紹。本文簡單介紹了32位程序和64位程序的區(qū)別,以及移植過程中需要注意的原則。實際上編寫同時能夠運行在32位和64位系統(tǒng)上的整體原則基本如下:

  1. 不要試圖假定數據類型的占用空間
  2. 顯示區(qū)別使用int和long

而前面提到的一些問題,其實通過一些代碼檢查工具就很容易發(fā)現了,不放過小的警告,基本能解決大部分問題。


當前名稱:32位程序和64位程序這些區(qū)別你知道嗎?
網頁網址:http://www.dlmjj.cn/article/dhcssdi.html