c++ - compiler - gcc教學




誰決定任何數據類型或結構的大小(取決於32位還是64位)? (5)

嚴格地說,100%完全是編譯器決定sizeof(int)的值。 它不是系統和編譯器的組合。 它只是編譯器(和C / C ++語言規範)。

如果您開發iPad或iPhone應用程序,則可以在Mac上運行編譯器。 Mac和iPhone / iPac使用不同的處理器。 沒有任何關於你的Mac告訴編譯器應該在iPad上使用int的大小。

誰決定任何數據類型或結構的大小(取決於32位還是64位)? 編譯器還是處理器? 例如,對於32位系統, sizeof(int)是4個字節,而對於64位系統, sizeof(int)是8個字節。

我還讀到,使用32位和64位編譯器編譯時, sizeof(int)是4個字節。

假設我的CPU可以運行32位和64位應用程序,誰將在決定編譯器或處理器的數據大小方面發揮主要作用?


它不是CPU,也不是編譯器,也不是操作系統。 這三個是同時進行的。

編譯器不能只是搞砸了。 它必須遵守操作系統提供的正確的ABI [1]。 如果操作系統提供的結構和系統調用具有某些大小和對齊要求的類型,那麼除非編譯器開發人員想要為操作系統提供的所有內容重新實現包裝函數,否則編譯器實際上無法自行構建自己的實際情況。 然後操作系統的ABI不能完全組成,它必須做可以在CPU上合理完成的事情。 通常,一個操作系統的ABI與同一CPU上其他操作系統的其他ABI非常相似,因為它更容易重用他們所做的工作(在編譯器等)。

如果計算機同時支持32位和64位代碼,則操作系統仍需要完成工作以支持在兩種模式下運行程序(因為系統必須提供兩種不同的ABI)。 有些操作系統沒有這樣做,而有些操作系統則沒有選擇。

[1] ABI代表應用程序二進制接口。 它是程序如何與操作系統交互的一組規則。 它定義了程序如何存儲在磁盤上以便操作系統可以運行,如何進行系統調用,如何與庫鏈接等等。但是為了能夠鏈接到庫,例如,您的程序和庫必須同意關於如何在程序和庫之間進行函數調用(反之亦然),並且為了能夠進行函數調用,程序和庫必須具有相同的堆棧佈局,寄存器用法,函數調用約定等概念。對於函數調用,您需要就參數的含義達成一致,包括類型的大小,對齊和簽名。


它最終是編譯器。 無論CPU處理效率最高,編譯器實現者都可以決定模擬他們認為合適的整數大小。 也就是說,編寫C(和C ++)標準,編譯器實現者可以自由選擇最快,最有效的方法。 對於許多編譯器,實現者選擇將int保持為32位,儘管CPU本身非常有效地處理64位整數。

我認為這部分是為了增加對32位機器最常見並且期望int為32位而不再是int的程序的可移植性。 (也可能是,正如用戶user3386109指出的那樣 ,32位數據是首選,因為它佔用的空間更少,因此可以更快地訪問。)

因此,如果您想確保獲得64位整數,則使用int64_t而不是int來聲明您的變量。 如果您知道您的值將適合32位或您不關心大小,則使用int讓編譯器選擇最有效的表示。

至於其他數據類型,例如struct ,它們由諸如int類的基類型組成。


當你談到編譯器時,你就可以獲得一個關於build|host|target的清晰圖像,即你正在構建的機器(構建),你正在構建的機器(主機),以及GCC將生成的機器(目標)的代碼,因為“交叉編譯”與“本機編譯”非常不同。

關於“誰決定sizeof數據類型和結構”的問題,它取決於你告訴編譯器為其構建二進製文件的目標系統。 如果target是64位,編譯器會將sizeof(long)轉換為8,如果目標是32位機器,編譯器會將sizeof(long)轉換為4.所有這些都是由用於構建的頭文件預定義的你的計劃。 如果您讀取`$ MAKETOP / usr / include / stdint.h',則有typedef來定義數據類型的大小。

為了避免由大小差異造成的錯誤, Google編碼樣式 -Integer_Types建議使用類型如int16_t,uint32_t,int64_t等。這些類型在<stdint.h>中定義。

上面只是那些“普通舊數據”,比如int。 如果你談論一個結構,還有另一個故事,因為結構的大小取決於打包對齊 ,結構中每個字段的邊界對齊,這將影響結構的大小。


處理器設計者確定哪些寄存器和指令可用,有效訪問的對齊規則是什麼,內存地址有多大等等。

C標准設置了內置類型的最低要求。 “char”必須至少為8位,“short”和“int”必須至少為16位,“long”必須至少為32位,“long long”必須至少為64位。 它還說“char”必須與程序可以解決的最小內存單元相等,並且必須保持標準類型的大小順序。

其他標準也可能產生影響。 例如,“單一Unix規範”的版本2表示int必須至少為32位。

最後,現有代碼會產生影響。 移植已經很難了,沒有人想讓它變得更難。

將操作系統和編譯器移植到新CPU時,有人必須定義所謂的“C ABI”。 這定義了二進制代碼如何相互通信,包括。

  • 內置類型的大小和對齊要求。
  • 結構的包裝規則(以及它們的尺寸)。
  • 如何傳遞和返回參數
  • 如何管理堆棧

一般而言,一旦ABI被定義為CPU系列和OS的組合,它的變化不大(有時像“長雙”變化這樣的更模糊類型的大小)。 改變它會帶來一堆破損,收益相對較小。

類似地,將操作系統移植到具有與現有操作系統類似特徵的平台的那些通常會選擇與移植到操作系統的先前平台相同的大小。

實際上,OS /編譯器供應商通常會選擇基本整數類型的幾種大小組合之一。

  • “LP32”:char是8位。 short和int是16位,long和指針是32位。 常用於8位和16位平台。
  • “ILP32”:char為8位,short為16位。 int,long和指針都是32位。 如果長時間存在則為64位。 常用於32位平台。
  • “LLP64”:char是8位。 short是16位。 int和long是32位。 long long和指針是64位。 用於64位窗口。
  • “LP64”:char是8位。 short是16位。 int是32位。 long,long long和指針是64位。 用於大多數64位unix類系統。
  • “ILP64”:char為8位,short為16位,int,long和指針,long long均為64位。 顯然在一些早期的64位操作系統上使用,但現在很少見。

64位處理器通常可以運行32位和64位二進製文件。 通常,這是通過在操作系統中使用兼容層來處理的。 因此,您的32位二進製文件使用與在32位系統上運行時相同的數據類型,然後兼容層會轉換系統調用,以便64位操作系統可以處理它們。





operating-system