仅限c++:0x80000000的一元减号

c++ only: unary minus for 0x80000000

本文关键字:一元 c++ 0x80000000 仅限      更新时间:2023-10-16

这个问题应该是为语言律师提出的。

假设有符号和无符号int都是32位宽。如n3337.pdf草案5.3.1.8所述,

(-(0x80000000u)) = 0x100000000u-0x80000000u = 0x80000000u

但我找不到这个问题的答案:对于签名0x80000000,一元减号是什么?是UB、定义的实现,还是?

这个问题主要是关于运行时计算的

   signed int my_minus(signed int i) { return -i;}
   ....
   int main() {
       signed int a = -0x7FFFFFFF; // a looks like 0x80000001
       signed int b = a - 1;       // b looks like 0x80000000
       std::cout << my_minus(b);
       ....
   }

尽管如此,欢迎您对其他2个案例的评论:

  • 编译时间常数折叠,例如-(INT_MIN)

  • constexpr的编译时间计算(如果与编译时间常数折叠有差异)。


(请看https://meta.stackexchange.com/questions/123713/is-splitting-a-question-a-good-practice在投票支持重复之前。)

据我所知,有符号整数溢出总是未定义的。来自C++规范部分5表达式,第4段:

如果在表达式的求值过程中,结果没有在数学上定义,或者不在其类型的可表示值范围内,则行为是未定义的。[注意:大多数现有的C++实现都忽略整数溢出。被零除法、使用零除数形成余数以及所有浮点异常的处理方式因机器而异,通常可通过库函数进行调整。--endnote]

有符号积分类型遵守数学整数的规则,而不添加计算机废话。因此,如果给定的类型不能表示结果数字,那么-std::numeric_limits< signed_type >::min()将是未定义的行为。

constexpr中,实现是拒绝该表达式所必需的,因为作为可诊断规则,任何导致未定义行为的行为都会使常量表达式无效。在这种情况下,该规则是§5.19中的禁止项目之一

--未在数学上定义或不在其类型的可表示值范围内的结果;

在常量折叠中,编译器最有可能插入溢出的值。