Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将无符号[char,short,int,long]转换为double的结果不一致_C++_C - Fatal编程技术网

C++ 将无符号[char,short,int,long]转换为double的结果不一致

C++ 将无符号[char,short,int,long]转换为double的结果不一致,c++,c,C++,C,为什么结果不一致,某些类型的结果为-10,而其他类型的结果为巨大值?一元-运算符的操作数被提升;小于int的类型将升级为int或无符号int 由于(有符号)int可以保存可由无符号字符表示的所有值,因此值(无符号字符)10将提升为有符号int值10。求反得到(有符号的)int值-10,然后将其转换为双精度 unsigned int不会“升级”为int,因为int不能保存所有值。因此表达式-e应用了无符号int求反运算符,这显然不能产生负值。结果是UINT_MAX+1-10,在您的系统上是4294

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

一元
-
运算符的操作数被提升;小于
int
的类型将升级为
int
无符号int

由于(有符号)
int
可以保存可由
无符号字符表示的所有值,因此值
(无符号字符)10
将提升为有符号
int
10
。求反得到(有符号的)
int
-10
,然后将其转换为
双精度

unsigned int
不会“升级”为
int
,因为
int
不能保存所有值。因此表达式
-e
应用了
无符号int
求反运算符,这显然不能产生负值。结果是
UINT_MAX+1-10
,在您的系统上是
4294967286
。转换为
double
将生成您看到的值

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


除了提升规则之外,重要的是要记住C表达式的类型(几乎总是)不受其出现的上下文的影响
-f
产生相同值和类型的结果,而不管它被分配给什么。

积分提升将前两个转换为更大的有符号类型(
int
);对于第二个问题:只对无符号类型应用一元负号。为什么这被认为是一个糟糕的问题?我被反对票弄糊涂了。稍微解释一下为什么观察到的结果令人惊讶是有帮助的,但是关于C表达式计算的一个相当微妙的方面,这是一个有效的问题。请有人评论和解释一下好吗?@DyP我也认为这个问题很好。它是精心编写的,显示了示例代码,并描述了一个不明显的问题(一元运算符积分提升)。这是不需要使用C++中的无符号类型的原因之一,除非您需要模运算。想要禁止否定值是不够的,我听说C++委员会成员表示遗憾,他们指定标准库的部分使用该基础上的未签名类型。不应该将<代码>未签名的长< /COD>情况转换为<代码> ULUNYOXMAX + 1 - 10 < /C>(不<代码> UTIN MAX < /COD>)?我肯定这只是一个打字错误…就像关于
18446744073709551606
转换为
18446744073709551616.000000
的部分一样。
#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