【问题标题】:c++ only: unary minus for 0x80000000仅限 c++:0x80000000 的一元减号
【发布时间】:2012-03-17 13:49:51
【问题描述】:

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

假设 signed 和 unsigned int 都是 32 位宽。如 n3337.pdf 草案 5.3.1.8 中所述,

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

但我找不到问题的答案:signed 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 个案例的 cmets:

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

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


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

【问题讨论】:

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


【解决方案1】:

有符号整数类型遵守数学整数的规则,没有添加计算机废话。所以-std::numeric_limits&lt; signed_type &gt;::min() 将是未定义的行为,如果给定的类型不能代表结果数字。

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

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2012-03-17
      • 2015-07-02
      • 2019-10-07
      • 1970-01-01
      • 2011-02-02
      • 2023-03-03
      • 1970-01-01
      • 2012-05-20
      • 1970-01-01
      相关资源
      最近更新 更多