现在的位置: 首页 > 综合 > 正文

C专家编程-整型提升与寻常算术转换

2017年12月15日 ⁄ 综合 ⁄ 共 1452字 ⁄ 字号 评论关闭

1 字符和整型(整型提升)

      如果char、short int或者int型位段(bit-field),包括它们有符号或无符号变型,以及枚举类型,可以使用在需要int或者unsigned int的表达式中。如果int可以完整表示源类型的所有值,那么该源类型的值就转换为int,否则转换为unsigned int。这称为整型提升。

2 寻常算术转换

     许多操作数类型为算术类型的双目运算符会引发转换,并以类似的方式产生结果类型。它的目的的产生一个普通类型,同时也是运算结果的类型。这个模式成为“寻常算术转换”。

      如果其中一个操作数类型是long double,那么另一个操作数也被转换为long double。其次如果一个操作数的类型是double,那么另一个操作数也被转换为double,再次,如果其中一个操作数的类型是float,那么另一个操作数也被转换为float。否则两个操作数进行整形升级,执行下面的规则:

      如果其中一个操作数的类型是unsigned long int,那么另一个操作数也被转换成unsigned long int。其次,如果其中一个操作数类型是long int,而另一个操作数的类型是unsigned int,如果long int能够完整表示unsigned int的所有值,那么unsigned int 类型操作数操作数被转换为long int,如果long int 不能完整表示unsigned int的所有值,那么两个操作数都被转换为unsigned long int。再次,如果一个操作数的类型是long
int,那么另一个操作数被转换为long int。再再次,如果一个操作数的类型是是unsigned int,那么另一个操作数被转换为unsigned int。如果所有以上情况都不属于,那么两个操作数都为int。

      采用通俗语言大意如下:

      当执行算术运算时,操作数的类型如果不同,就会发生转换。数据类型一般朝着浮点精度更高、长度更长的方向转换,整型数如果转换为signed不会丢失信息,就转换为signed,否则转换为unsigned。

int array[] = { 23, 34, 12, 17, 204, 99, 16 };
#define TOTAL_ELEMENTS (sizeof(array)/sizeof(array[0]))

int main()
{
   int d = -1, x;
   /*...*/
   if (d <= TOTAL_ELEMENTS - 2)
   {
       x = array[d+1];
   }
   /*...*/
}

TOTAL_ELEMENTS所定义的值是unsigned int 类型(因为sizeof()的返回类型是无符号数)。
if语句在signed int和unsigned int 之间测试相等性,所以d被升级为unsigned int类型,
-1 转换成unsigned int 的结果将是一个非常巨大的正整数。致使表达式的值为假。

修复这个bug:
if (d < (int)TOTAL_ELEMENTS - 2)
{
//...
}

3 对无符号类型的建议

    1 尽量不要再你的代码中使用无符号类型,以免正价不必要的复杂性。尤其是,不要因为无符号数不存在负值(如年龄、国债)而用它来表示数量。

    2 尽量使用像int那样的有符号类型,这样在涉及升级混合类型的复杂细节时,不必担心边界情况(如-1被翻译为非常大的正数)

    3 只有在使用位段和二进制掩码时,才可以用无符号数。应该在表达式中使用强制类型转换,使操作数均为有符号数或者无符号数,这样就不必由编译器来选择结果的类型。

抱歉!评论已关闭.