2017-01-11 41 views
3

我注意到,對於8位變量的簡單操作,變量在操作完成之前轉換爲32位int s,然後轉換回8位變量。爲什麼uint8_t + uint8_t會導致int?

作爲一個例子,這個C++程序:

#include <iostream> 
#include <cstdint> 

int main(void) 
{ 
    uint8_t a = 1; 
    uint8_t b = 2; 

    std::cout << "sizeof(a) = " << sizeof(a) << std::endl; 
    std::cout << "sizeof(b) = " << sizeof(b) << std::endl; 
    std::cout << "sizeof(a+b) = " << sizeof(a+b) << std::endl; 

    return 0; 
} 

產生以下輸出:

sizeof(a) = 1 
sizeof(b) = 1 
sizeof(a+b) = 4 

因此,我們可以明白,什麼情況是:

uint8_t c = (uint8_t)((int)(a) + (int)(b)); 

顯然,這似乎是在this論壇中說的C規範。

此外,在Visual Studio 2013,寫

auto c = a + b; 

而超過c將鼠標指針指示該類型是int

的問題是:

  • 爲什麼轉換需要,爲什麼在規範呢? (如果可能,有了答案,我希望外部信息來源閱讀有關該主題的更多信息(如MSDN,cppreference)。)
  • 這會如何影響性能?

回答

2

的問題是:

  • 爲什麼轉換需要,爲什麼在規範呢? (如果可能的話,有了答案,我希望外部信息來源閱讀關於此主題的更多 (如MSDN,cppreference)。)
  • 這會如何影響性能?

好,

  • 對C++的算術運算符采取整體操作數的要求可以發現here

  • 積分促銷的規律可尋here

至於爲什麼它在規範。假設......雖然CPU可能具有可以在8位整數上運行的指令,但在CPU內,寫入/讀取小於寄存器寬度的整數可能會涉及您不知道的掩碼。

假設你有32位寄存器寬度。添加兩個8位整數通常需要一些掩碼來獲取8位部分並將剩餘的24位填充爲0 ...... ALU將對寄存器中的數據執行工作,並將結果存儲在完整寄存器寫入(32位)中。然後另一個掩碼檢索結果作爲一個8位整數,如果你投回..

因此,推動它不會花費任何東西,因爲無論如何CPU會這樣做。

參見:On 32-bit CPUs, is an 'integer' type more efficient than a 'short' type?

即使你regular 32bit operations on 64bits

6

這是由於integral promotion規則。具體地小整型

Prvalues(如char)可被轉換成較大的整數類型的prvalues(如int)。 特別是,算術運算符不接受類型小於int的類型作爲參數,並且積分促銷在左值到右值轉換後自動應用(如果適用)。此轉換始終保留該值。

+1

* 「爲什麼轉換需要,爲什麼在規範呢?」 * – WhiZTiM

+1

想象一下,你做'uint8_t A = 200,B = 100,C = 2; uint8_t d =(a + b)/ c;'沒有升級,中間結果會溢出 - 隨着升級,所有內容都將以150爲最終目標。 –

+3

@JesperJuhl *「..沒有提升中間結果會溢出」* - 'int a = INT_MAX,b = 343232;無論如何,int c = a + b'仍然會溢出...所以呢? – WhiZTiM