C++ 0x8000000的一元减号(有符号和无符号)
n3337.pdf草案5.3.1.8规定: 一元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
-
运算符的操作数应具有算术或非作用域枚举类型,结果是其操作数的求反。对整数或枚举操作数执行整数提升。无符号量的负值是通过从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
,您通常会看到崩溃。