这个问题应该是针对语言律师的。
假设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。)
答案 0 :(得分:4)
据我所知,有符号整数溢出始终未定义。从C ++规范部分 5表达式,第4段:
如果在评估表达式期间,结果未在数学上定义或未在其类型的可表示值范围内,则行为未定义。 [注意:大多数现有的C ++实现忽略整数溢出。除零处理,使用零除数形成余数,所有浮点异常因机器而异,通常可通过库函数调整。 -endnote
答案 1 :(得分:3)
有符号整数类型遵守数学整数规则而不添加计算机废话。因此,-std::numeric_limits< signed_type >::min()
将是未定义的行为,如果给定的类型不能代表结果数字。
在constexpr
中,实现 required 拒绝该表达式,因为任何导致未定义行为的内容都会使常量表达式无效,作为可诊断规则。在这种情况下,规则是§5.19中的禁止项之一,
- 未在数学上定义的结果或不在其类型的可表示值范围内的结果;
在常量折叠中,编译器最有可能插入溢出值。