测试几个编译器(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,还是依赖于此实现?
谢谢,
答案 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积分促销
char
,signed char
类型的右值,unsigned char
,short int
或unsigned 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)
short
与short int
不一样吗?与long
与int
同义的方式相同。例如。 short
int
占用的内存少于标准int
?
答案 4 :(得分:0)
int
应该是任何给定机器架构的自然字大小,并且许多机器具有仅(或至少最佳地)对机器字执行算术运算的指令。
如果语言是在没有整数提升的情况下定义的,那么许多多步计算本来可以自然地直接映射到机器指令中,可能必须穿插对中间体执行的屏蔽操作,以生成“正确”的结果。
答案 5 :(得分:0)
C和C ++都不会对小于int
的类型执行任何算术运算。只要您指定较小的操作数(任何char
或short
),操作数就会被提升为int
或unsigned int
,具体取决于范围。