C++ 0x8000000的一元减号(有符号和无符号)

C++ 0x8000000的一元减号(有符号和无符号),c++,c,standards,unary-operator,C++,C,Standards,Unary Operator,n3337.pdf草案5.3.1.8规定: 一元-运算符的操作数应具有算术或非作用域枚举类型,结果是其操作数的求反。对整数或枚举操作数执行整数提升。无符号量的负值是通过从2中减去其值来计算的ⁿ, 其中n是提升操作数中的位数。结果的类型是提升的操作数的类型 在某些情况下,这就足够了。假设无符号整数是32位宽,那么((0x80000000u))==0x80000000u,不是吗 不过,我在未签名的0x8000000上找不到任何关于一元负号的信息。此外,C99标准草案n1336.pdf,6.5.3.3

n3337.pdf草案5.3.1.8规定:

一元
-
运算符的操作数应具有算术或非作用域枚举类型,结果是其操作数的求反。对整数或枚举操作数执行整数提升。无符号量的负值是通过从2中减去其值来计算的ⁿ, 其中n是提升操作数中的位数。结果的类型是提升的操作数的类型

在某些情况下,这就足够了。假设无符号整数是32位宽,那么
((0x80000000u))==0x80000000u
,不是吗

不过,我在未签名的0x8000000上找不到任何关于一元负号的信息。此外,C99标准草案n1336.pdf,6.5.3.3似乎没有提及:

一元运算符的结果是其(提升的)操作数的负数。对操作数执行整数提升,结果具有提升类型

UPDATE2:假设unsigned int的宽度为32位。所以问题是:C中的一元减法(符号和无符号)和C++中的一元减法(仅签名)是什么?< /P> 更新1:运行时行为和编译时行为(即常量折叠)都很有趣


(相关:)

在n1336,6.3.1.3有符号和无符号整数中,第2段定义了到无符号整数的转换:

否则,如果新类型是无符号的,则该值将由 重复地加上或减去一个大于最大值 可以在新类型中表示,直到值在 新型的


因此,对于32位无符号整数,
-0x80000000u==-0x80000000+0x100000000==0x80000000u

对于您的问题,您引用的重要部分如下:

无符号量的负数是通过减去其 值从2开始ⁿ, 其中n是提升操作数中的位数

因此,要知道
-0x80000000u
的值是多少,我们需要知道
n
,即
0x80000000u
类型中的位数。这至少是32个,但这是我们所知道的全部(没有关于实现中类型大小的进一步信息)。给定
n
的一些值,我们可以计算结果:

n   | -0x80000000u 
----+--------------
32  | 0x80000000
33  | 0x180000000
34  | 0x380000000
48  | 0xFFFF80000000
64  | 0xFFFFFFFF80000000
(例如,
unsigned int
为16位且
unsigned long
为64位的实现将具有64位的
n


C99具有隐藏在§6.2.5 p9类型中的等效措辞:

涉及无符号操作数的计算永远不会溢出,因为 无法由结果无符号整数表示的结果 类型按比最大值大一的数的模减少 可由结果类型表示的值

此规则将始终捕获非零无符号操作数上的一元
-
运算符的结果

对于32位
int
0x8000000
的类型将是
unsigned int
,而不管是否缺少
u
后缀,因此结果仍然是
0x8000000
类型为
unsigned int
的值


如果改为使用十进制常量
2147483648
,则其类型将为
long
,并且计算将被签名。结果将是值
-2147483648
,类型为
long

您的意思是在有符号的0x8000000上找不到任何关于一元负号的信息吗?通常编译器只会生成一个适当的CPU操作码(例如)。标准措辞只是试图正式描述实际发生的事情。@GregHewgill:我认为问题的关键在于C99标准没有描述发生的事情。我不明白你在问什么。在大多数平台上,0x80000000上的一元数等于0x80000000,因为0x100000000-0x80000000=0x80000000。@sth c99标准似乎完全没有提到角大小写,即:6.5.3.3.3:一元数运算符的结果是其(提升的)操作数的负数。整数提升是在操作数上执行的,结果具有提升的类型。您正在假设常量
0x8000000
@caf的类型中可以表示的最大值,啊,是的。好吧,无论如何你都会得到答案。我认为int保证至少是32位,不是吗?@daupic:不,
int
保证至少是16位,
long
保证至少是32位,
long
保证至少是64位。要将其四舍五入,
char
保证至少为8位,
short
保证至少为16位。请注意,POSIX要求
int
至少为32位。@caf确定。假设无符号整数为32位宽。我仍然对C++中的int int 0x800 0的一元减号感兴趣。@ USER 1123502:如果<代码> -INTHINMIN/COD>不能表示(如在两个补码实现上),则该行为未按照C99第6.5表达式P5定义。在实践中,您不会经常看到崩溃,但对于其他类似的表达式,例如
INT\u MIN/-1
,您通常会看到崩溃。