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

按位“或”运算符在带符号扩展操作数上使用;请考虑首先强制转换为较小的无符号类型

2013年10月20日 ⁄ 综合 ⁄ 共 1460字 ⁄ 字号 评论关闭

按位“或”运算符在带符号扩展操作数上使用;请考虑首先强制转换为较小的无符号类型 

错误:
 long r = 0;
 r |= (buf[i] & 0x00000000000000ff);
正确:
 long r = 0;

 r |= Convert.ToInt64((buf[i] & 0x00000000000000ff));   先转换为long型再执行或运算

或者

 r |= (buf[i] & long(0x00000000000000ff));   先转换为long型再执行或运算

参考:
(摘自C专家编程)
    字符和整型(整型升级)
    char,short int或者int型位段(bit-field),包括它们的有符号或无符号类型,以及枚举类型,可以使用在需要int或unsigned int的表达式中。如果int可以完整表示源类型的所有值(即int是32位,译者注),那么该源类型的值就转换为int,否则转换为unsigned int。这称为整型升级。
    寻常算术转换
    许多操作数类型为算术类型的双目运算符会引发转换,并以类似的方式产生结果类型。它的目的是产生一个普通类型,同时也是运算结果的类型,这个模式称为“寻常算术转换“。
    首先,如果其中一个操作数是long double,那么另一个操作数也被转换为long double。其次,如果其中一个操作数的类型是double,那么另一个操作数也被转换为double。再次,如果其中一个操作数的类型是float,那么另一个操作数也被转换为float。否则,两个操作数执行整型升级,执行下面的规则:
    如果其中一个操作数的类型是unsigned long int,那么另一个操作数也被转换为unsigned long int。其次,如果其中一个操作数的类型是long int,而另一个操作数的类型是unsigned int,如果long int能够完整表示unsigned int的所有值(即long是32位而int是16位,译者注),那么unsigned int类型操作数被转换为long int,如果long int不能完整表示unsigned int的所有值(即long和int均为32位,译者注),那么两个操作数都被转换为unsigned
long int。再次,如果其中一个操作数是long int,那么另一个操作数被转换为long int。再再次,如果其中一个操作数的类型是unsigned int,那么另一个操作数被转换为unsigned int。如果所有以上情况都不属于,那么两个操作数都为int。
    通俗的说(当然存在漏洞,而且不够精确):当执行算术运算时,操作数的类型如果不同,就会发生转换。数据类型一般朝着浮点精度更高、长度更长的方向转换,整型数如果转换为signed不会丢失信息,就转换为signed,否则转换为unsigned。
    ANSI C标准采用值保留(value preserving)原则,就是当把几个整型操作数混合使用,结果类型有可能是有符号数,也有可能是无符号数,取决于操作数的类型的相对大小。
对无符号类型的建议:
    尽量不要在代码中使用无符号类型,以免增加不必要的复杂性。尤其是,不要仅仅因为无符号数不存在赋值(如年龄、国债)而用它来表示数量。
    尽量使用像int那样的有符号类型,这样在涉及升级混合类型的复杂细节时,不必担心边界情况(如-1被翻译成非常大的正数)。
    只有在使用位段和二进制掩码时,才可以使用无符号数。应该在表达式中使用强制类型转换,使操作数均为有符号数或者无符号数,这样就不必由编译器来选择结果的类型。

抱歉!评论已关闭.