Learning C++ 之 2.4a 定寬整數和無符號整數的爭論

   在前一章中你知道了C++一般只保證整數有一個最小取值範圍,但是他們可能更大,這個取決於你的操作系統。

爲什麼整型值的size不是確定的?

    簡單來說,非技術性的回答可以追溯到C語言,性能是最重要的。C語言故意預留了可調的整型數值的大小,以便編程者可以選擇一個對機器性能最高的整型數據size來使用。

這樣是不是不好?

當然。程序員不得不根據機器的性能來確認整型數值的size大小,這是非常荒繆的。

寬整型:

爲了可跨平臺,C99定義了一套寬整型來適配所有平臺。具體定義如下:

NameTypeRangeNotes
int8_t1 byte signed-128 to 127Treated like a signed char on many systems. See note below.
uint8_t1 byte unsigned0 to 255Treated like an unsigned char on many systems. See note below.
int16_t2 byte signed-32,768 to 32,767
uint16_t2 byte unsigned0 to 65,535
int32_t4 byte signed-2,147,483,648 to 2,147,483,647
uint32_t4 byte unsigned0 to 4,294,967,295
int64_t8 byte signed-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
uint64_t8 byte unsigned0 to 18,446,744,073,709,551,615

C++在C++11中正式接受了這種命名形式,可以通過引用cstdint頭文件來使用,這些定義在std標準命名空間裏,如下面的例子:

#include <iostream>
#include <cstdint>
 
int main()
{
    std::int16_t i(5); // direct initialization
    std::cout << i;
    return 0;
}

儘管在C++11之前不能正式使用該頭文件,但是在之前的版本中可以通過引用stdint.h來正式命名。如果你使用的是boost庫,那麼需要引用的路徑如下:<boost/cstdin.hpp>

如果你的編譯器不支持stdint.h,好消息是你可以下載Paul Hseih's pstdint.h(stdint.h的交叉編譯版厄本那)。在你的文件中引用一下pstdint.h你就可以使用這些通用寬度字節的整型變量了。

警告:int8_t,unint8_t可能並不像char類型的行爲一樣

由於C++標準的疏忽,大多數編譯器把int8_t和uint8_t和char,unsigned char一樣對待,但是又是這是沒有必要的。因此std::cout和std::cin可能和你期望的輸出不同,如下面的例子:

#include <cstdint>
#include <iostream>
 
int main()
{
    int8_t myint = 65;
    std::cout << myint;
 
    return 0;
}

在大多數系統裏都會輸出'A',但是有時候我們期望輸出65.

爲了簡單期間,最好避免使用int8_t和uint8_t,而是int16_t和unint16_t來替代。如果你非要用,一定要特別小心那些把int8_t和uint8_t與char,unsigned char重複使用的場景(如std::cin  std::cout)。

希望以後這會被C++協議澄清。

定寬整型的缺點

在一些無法表示這些類型的架構中可能不支持定寬整型,定寬整型在一些行內傷可能比普通的整型要差。

快速而簡潔的:

爲了解決上述問題,C++還定義了兩種可選的定寬整型數據集。

快速類型(int_fast#_t)提供了一種最快速的,位數最少是#位的數據類型。如int_fast32_t提供了至少32位的最快的整數類型。

最小類型(int_least#_t)提供了一種最小,位數至少是#位的整數類型。如int_least32_t提供了32位最小的整數類型。

整數最好的建議:

現在定寬整型已經化爲了C++11的標準之中,最好的練習如下:

  • 當整形的size無所謂時,首先推薦int。舉例來說假如你需要輸入用戶的年齡,或者從1到10,這樣整數的size大小是無所謂的.這基本涵蓋了你所遇到的大多數情況。
  • 如果你想要一個特殊size的變量,並且非常強調性能的話,建議用int_fast#_t:
  • 如果你需要一個特殊size的變量,並且相對對內存要求比較高的話,建議採用int_least#_t
  • 只有當你有明確需求的時候,使用unsigned int
一些編譯器有時候會定義自己的固定長度整型,比如VS就會有int16_t,int32_t,當然我們編譯程序的時候不建議使用這些。

關於無符號整數的爭論:

一些開發者建議應該儘量避免使用unsigned int,因爲當你搞混了signed和unsigned類型的時候,往往會出現意想不到的結果。

考慮下面的小段代碼:

void doSomething(unsigned int x)
{
    // Run some code x times
}
 
int main()
{
    doSomething(-1);
}

這種情況下會發生什麼事情麼?你的程序會爆掉,因爲unsigned會把你的-1程序轉化成一個極大值。更糟的是,沒有什麼好的方法來提前預防這件事情的發生。C++會自由轉換signed和unsigned的數值,但是他並不做size檢查。

一些現代的語言要麼不支持unsigned類型,要麼會限制他的使用。Bjarne Stroustrup說過:使用unsigned來獲取更多的位數來表示整型是一種不明智的做法。

這並不意味着你需要完全避免unsigned類型,但是如果你使用的時候,一定確認確實需要該類型,並且不能把signed和unsigned弄混了。

Note:本教程大部分在C++11之前寫的,所以我們可能更多地使用int。

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