为什么一元减号会执行整数提升?

6
const auto min = -std::numeric_limits<T>::max();
T x = min; // conversion from 'const int' to 'short', possible loss of data

T是一个模板参数,在这种情况下是一个short。一元负号显然执行整数提升。

  • 为什么一元负号会执行整数提升?
  • 如果将auto更改为T,不会生成警告,但应该将int赋给short。为什么没有警告(可能是VS很高级)?

4
为什么一元减号要执行整型提升?因为标准规定如此(见5.3.1. (7))。 - Daniel Fischer
5
但是,在制定标准的过程中,肯定有每个决定背后的原因,对吧?如果可能的话,帮助人们理解这种推理并不是一件坏事。 - Ed S.
3
@EdS. 是的,希望这些决定背后有原因。我不知道它们的原因,但我怀疑这个决定至少部分原因是“因为在C语言中就是这样”。那么为什么在C语言中会这样呢?我猜测这是因为让CPU使用本地类型并且不将结果转换回原始类型更简单。但这只是猜测。 - Daniel Fischer
3
@DanielFischer(第一个评论):那个答案让我(以及许多其他人)感到非常恼火,甚至不好笑… - user541686
4
如果某些算术运算遵循整数提升规则而有些则不遵循,那岂不更奇怪?那么你会问:“为什么整数提升适用时有两组不同的规则?为什么不能保持一致?”请注意,此翻译尽量保持原意并使内容通俗易懂,未包含任何额外解释。 - Raymond Chen
显示剩余10条评论
4个回答

6
简短回答:(现在变长因为人们过于追求英语的精确性,而英语本身并不是精确的)。它并不明确(如一元减号mathematical)。但是,在对POD数据进行任何操作(包括一元减号operation)时,会对输入参数进行隐式检查(可以在操作中使用的最小整数类型是int),因此一元减号(mathematical部分而非operation部分)之前会进行整数提升。POD上所有操作的输出与输入参数相同(应用了整数提升之后)。因此,这里的输出也是int
长篇回答:
在C(因此也是C++)中,POD操作发生的最小类型是int。因此,在应用一元减号之前,该值将转换为int。然后应用一元减号。因此表达式的结果是int
请参见这里:Implicit type conversion rules in C++ operators

4

一元减号执行整数提升,因为整数类型上的所有算术运算符都这样做。这种惯例可能是出于性能原因建立的(通常int是最适合硬件上的整数运算的大小),也许是因为有时不限制较小整数类型的范围是有用的。

我看过一些bug,人们会做:

uint64_t i = 1 << 33; // use 64-bit type to ensure enough bits to hold the result

但是这是一个bug,因为1 << 33的结果不取决于它被分配给什么。(今天我们有关于这个问题的警告)。解决方案很丑陋,需要手动强制其中一个操作数足够大:uint64_t i = static_cast<uint64_t>(1) << 33 整数提升可以避免较小类型的相同类型的错误,这在C语言设计时是常见的情况:
short a = 30000, b = 20000
int i = a + b;

无论如何,“它不必合乎逻辑。这就是法律。”


0

我认为这是为了考虑到C/C++所假设的理想计算机模型。计算是在寄存器中执行的,这意味着结果的大小将是机器字。因此出现了“自动扩展”的情况。


0

我认为这部分是因为一个short的负数可能无法表示为一个short
(-215如果short是16位且int更大,则可能需要提升为int。)

当然,不能保证int更大,但它通常是机器上最优数据类型,因此尝试将其提升为int是有意义的,因为可能没有性能成本。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接