在前一章中你知道了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。