use*_*502 2 c c++ standards unary-operator
n3337.pdf草案5.3.1.8规定:
一元运算
-符的操作数应具有算术或无范围的枚举类型,结果是其操作数的否定.对整数或枚举操作数执行整体提升.通过从2ⁿ减去其值来计算无符号数量的负数,其中n是提升的操作数中的位数.结果的类型是提升的操作数的类型.
在某些情况下,这就足够了.假设unsigned int是32位宽,那么(-(0x80000000u)) == 0x80000000u,不是吗?
不过,我找不到关于无符号0x80000000上的一元减号的任何内容.此外,C99标准草案n1336.pdf,6.5.3.3似乎没有提及:
一元运算符的结果是其(提升的)操作数的否定.整数提升在操作数上执行,结果具有提升类型.
UPDATE2:我们假设unsigned int是32位宽.所以,问题是:C中的一元减号(有符号和无符号),以及C++中的一元减号(仅限签名)?
UPDATE1:运行时行为和编译时行为(即常量折叠)都很有趣.
对于您的问题,您所包含的报价的重要部分是:
通过从2ⁿ减去其值来计算无符号数量的负数,其中n是提升的操作数中的位数.
所以,要知道它的价值-0x80000000u是什么,我们需要知道n,类型中的位数0x80000000u.这至少是32,但这是我们所知道的(没有关于实现中类型大小的更多信息).给定一些值n,我们可以计算结果:
n | -0x80000000u
----+--------------
32 | 0x80000000
33 | 0x180000000
34 | 0x380000000
48 | 0xFFFF80000000
64 | 0xFFFFFFFF80000000
Run Code Online (Sandbox Code Playgroud)
(例如,unsigned int16位且unsigned long64位的实现将具有64位n).
C99在§6.2.5类型p9中隐藏了相同的措辞:
涉及无符号操作数的计算永远不会溢出,因为无法通过生成的无符号整数类型表示的结果将以比结果类型可以表示的最大值大1的数量为模.
-除了零之外的无符号操作数上的一元运算符的结果将始终被此规则捕获.
对于32位int,类型0x80000000将是unsigned int,无论u后缀是否缺少,因此结果仍然是0x80000000类型的值unsigned int.
如果您使用十进制常量2147483648,它将具有类型long并且将对计算进行计算.结果将是-2147483648类型的值long.