• 有符号数和无符号数------c++程序设计原理与实践(进阶篇)


    有符号数与无符号数的程序设计原则:

    • 当需要表示数值时,使用有符号数(如 int)。
    • 当需要表示位集合时,使用无符号数(如unsigned int)。

    有符号数和无符号数混合运算有可能会带来灾难性的后果。例如:

    vector<int> v;
    for(int i=0;i<v.size();++i)cout<<v[i]<<'
    ';
    

    易实现版本:

    unsigned char max=160;    //非常大
    for(signed char i=0;i<max;i++)cout<<int(i)<<'
    ';

      循环变量i可能会溢出,即,v.size()有可能比最大的有符号数int值还要大。当i的值增大到有符号数int所能代表的最大正数(如,int为16位宽度,此值为215-1)时,下一次增1运算不会得到更大的整型值,而会得到一个负数。因此循环永远也不会停止!每当我们到达最大整数时,接着就会从最小负int值重新开始。因此如果v.size()的值为32*1024或者更大,循环变量为16位int型的话,这个循环就是一个(可能非常严重的)bug。如果循环变量是32位int型的话,当v.size()的值大于等于2*1024*1024*1024时就会出现同样的问题。

      为了避免这个问题,我们可以使用vector提供的size_tupe或者是迭代器:

    for(vector<int>::size_type i=0;i<v.size();++i)cout<<v[i]<<'
    ';
    for(vector<int>::iterator p=v.begin();p!=v.end();++p)cout<<*p<<'
    ';
    for(int x:v)cout<<x<<'
    ';
    

      size_tupe确保是无符号的,因此,第一种形式(使用无符号数)与int型循环变量的版本相比,多出一个二进制位来表示循环变量的数值(而不是符号)。这个改进很重要,但终究只是多出一位来表示循环的范围(循环次数多出一倍)。而使用迭代器的版本就不存在这个限制。

      大致来说,我们有两个原因将无符号数当作整数来使用,而不是简单作为一组二进制位(即,不使用+、-、*和/);

    • 有更多的二进制位来表示数值,从而获得更高的精度。
    • 用来表示逻辑属性,其值不能是负数。

    前者就是我们刚刚看到的,使用无符号循环变量带来的效果。

      混合使用有符号数和无符号数的问题在于,在c++中,两者转换的方式很奇怪,而且难以记忆。例如:

    unsigned int ui=-1;
    int si=ui;
    int si2=ui+2;
    unsigned ui2=ui+2;
    

      输出结果:

    4294967295
    -1
    1
    1

    不推荐为获得一个额外的二进制位的精度而是要无符号数。

    标准库容器的下标都是无符号数。

    c++程序设计原理与实践(进阶篇)

  • 相关阅读:
    泛函编程(29)-泛函实用结构:Trampoline-不再怕StackOverflow
    泛函编程(28)-粗俗浅解:Functor, Applicative, Monad
    泛函编程(27)-泛函编程模式-Monad Transformer
    泛函编程(26)-泛函数据类型-Monad-Applicative Functor Traversal
    泛函编程(25)-泛函数据类型-Monad-Applicative
    mac安装iterm2
    像使用linux一样使用mac
    springboot工程自动生成工具
    mysql insert返回主键
    linux rz sz命令
  • 原文地址:https://www.cnblogs.com/l2017/p/7854135.html
Copyright © 2020-2023  润新知