在前一章中你知道了C++一般只保證整數有一個最小取值範圍,但是他們可能更大,這個取決於你的操作系統。
爲什麼整型值的size不是確定的?
簡單來說,非技術性的回答可以追溯到C語言,性能是最重要的。C語言故意預留了可調的整型數值的大小,以便編程者可以選擇一個對機器性能最高的整型數據size來使用。
這樣是不是不好?
當然。程序員不得不根據機器的性能來確認整型數值的size大小,這是非常荒繆的。
寬整型:
爲了可跨平臺,C99定義了一套寬整型來適配所有平臺。具體定義如下:
Name | Type | Range | Notes |
---|---|---|---|
int8_t | 1 byte signed | -128 to 127 | Treated like a signed char on many systems. See note below. |
uint8_t | 1 byte unsigned | 0 to 255 | Treated like an unsigned char on many systems. See note below. |
int16_t | 2 byte signed | -32,768 to 32,767 | |
uint16_t | 2 byte unsigned | 0 to 65,535 | |
int32_t | 4 byte signed | -2,147,483,648 to 2,147,483,647 | |
uint32_t | 4 byte unsigned | 0 to 4,294,967,295 | |
int64_t | 8 byte signed | -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 | |
uint64_t | 8 byte unsigned | 0 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
關於無符號整數的爭論:
一些開發者建議應該儘量避免使用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。