仅限c ++:一元减去0x80000000

时间:2012-02-28 03:35:41

标签: c++ standards language-lawyer unary-operator

这个问题应该是针对语言律师的。

假设signed和unsigned 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。)

2 个答案:

答案 0 :(得分:4)

据我所知,有符号整数溢出始终未定义。从C ++规范部分 5表达式,第4段:

  

如果在评估表达式期间,结果未在数学上定义或未在其类型的可表示值范围内,则行为未定义。 [注意:大多数现有的C ++实现忽略整数溢出。除零处理,使用零除数形成余数,所有浮点异常因机器而异,通常可通过库函数调整。 -endnote

答案 1 :(得分:3)

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

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

  

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

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