C ++中按位运算符的结果

时间:2010-07-28 21:23:29

标签: c++

测试几个编译器(Comeau,g ++)确认某些“整数类型”的按位运算符的结果是int:

void foo( unsigned char );
void foo( unsigned short );

unsigned char a, b;

foo (a | b);

我原本期望“a | b”的类型是unsigned char,因为两个操作数都是unsigned char,但是编译器说结果是int,并且对foo()的调用是不明确的。为什么设计语言使得结果是int,还是依赖于此实现?

谢谢,

6 个答案:

答案 0 :(得分:9)

这实际上是标准C ++行为(ISO / IEC 14882):

  

5.13 / 1按位包含OR运算符

     

通常的算术转换是   执行;结果是按位   包含其操作数的OR功能。   操作员仅适用于积分   或枚举操作数。

     

5/9通常的算术转换

     

许多期望的二元运算符   算术或枚举的操作数   类型导致转换和产量   结果类型以类似的方式。目的   是产生一种普通类型,也是   结果的类型。这个   pattern被称为通常的算术   转化,定义为   如下:

     
      
  • 如果任一操作数的类型为long double,   另一个应转换为long double
  •   
  • 否则,如果任一操作数为double,   另一个应转换为double
  •   
  • 否则,如果任一操作数为float,   另一个应转换为float
  •   
  • 否则,积分促销   应在两个操作数上执行。
  •   
  • ...
  •   
     

4.5 / 1积分促销

     

charsigned char类型的右值,   unsigned charshort intunsigned short int可以转换为   如果int可以,则int类型的右值   表示源的所有值   类型;否则,源rvalue可以   转换为unsigned int类型的右值。

我认为这与int所谓的执行环境的“自然”大小有关,以便进行有效的算术运算(参见Charles Bailey's answer)。

答案 1 :(得分:1)

  

我原本期望“a | b”的类型是unsigned char,因为两个操作数都是unsigned char,

我在过去读过一些初学者的C书,给人的印象是按位操作符只是为了系统编程而保留在语言中,并且通常应该避免使用。

操作符由CPU本身执行。 CPU用于操作数寄存器(肯定比char大),因此编译器无法知道操作会影响寄存器的多少位。为了不松开操作的全部结果,编译器将结果向上转换为正确的操作。 AFAICT。

  

为什么设计语言使得结果是int,还是依赖于此实现?

数据类型的位级表示实际上是实现定义的。这可能是明显按位操作也是实现定义的原因。

虽然C99在6.2.6.2 Integer types中定义它们应该如何出现和表现(以及后来的按位操作应该如何工作),但特定章节为实现提供了很大的自由。

答案 2 :(得分:0)

这似乎与Java中的相同:

Short和char(以及小于int的其他整数)是比int更弱的类型。因此,对这些较弱类型的每个操作都会自动取消装入int。

如果你真的想得到一个简短的话,你就必须对它进行类型化。

不幸的是我不能告诉你为什么这样做了,但这似乎是一个相对常见的语言决定......

答案 3 :(得分:0)

shortshort int不一样吗?与longint同义的方式相同。例如。 short int占用的内存少于标准int

答案 4 :(得分:0)

int应该是任何给定机器架构的自然字大小,并且许多机器具有仅(或至少最佳地)对机器字执行算术运算的指令。

如果语言是在没有整数提升的情况下定义的,那么许多多步计算本来可以自然地直接映射到机器指令中,可能必须穿插对中间体执行的屏蔽操作,以生成“正确”的结果。

答案 5 :(得分:0)

C和C ++都不会对小于int的类型执行任何算术运算。只要您指定较小的操作数(任何charshort),操作数就会被提升为intunsigned int,具体取决于范围。