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。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值