将unsigned [char,short,int,long]转换为double的结果不一致

时间:2013-11-19 19:26:03

标签: c++ c

#include <stdio.h>

int main(int argc, char* argv[]) {
  unsigned char c = 10;
  unsigned short d = 10;
  unsigned int e = 10;
  unsigned long f = 10;
  double g = -c;
  double h = -d;
  double i = -e;
  double j = -f;
  printf("%d %lf\n", c, g);
  printf("%u %lf\n", d, h);
  printf("%u %lf\n", e, i);
  printf("%lu %lf\n", f, j);
}

作为输出

10 -10.000000
10 -10.000000
10 4294967286.000000
10 18446744073709551616.000000

为什么结果不一致,某些类型产生-10,其他类型产生巨大价值?

1 个答案:

答案 0 :(得分:13)

一元-运算符的操作数是提升;比int更窄的类型被提升为intunsigned int

由于(已签名)int可以包含unsigned char可以表示的所有值,因此值(unsigned char)10会提升为已签名 {{ 1}}值int。否定为您提供(签名)10int,然后将其转换为-10

double未被“提升”为unsigned int,因为int无法保存所有值。因此表达式int应用-e否定运算符,这显然不会产生负值。结果为unsigned int,您的系统上的结果为UINT_MAX + 1 - 10。转换为4294967286会产生您看到的值。

同样,double未升级,因此unsigned long会产生-f,转换为ULONG_MAX + 1 - 10时会产生double(2 64 -10)(显然你的系统有64位18446744073709551606long)。将该值转换为unsigned long会失去一些精确度,从而产生您看到的值。

除了促销规则之外,重要的是要记住C表达式的类型(几乎总是)不受其出现的上下文的影响。 double生成相同值和类型的结果,无论它分配给什么。