当前位置:  开发笔记 > 编程语言 > 正文

为什么0 <-0x80000000?

如何解决《为什么0<-0x80000000?》经验,为你挑选了6个好方法。

我有一个简单的程序:

#include 

#define INT32_MIN        (-0x80000000)

int main(void) 
{
    long long bal = 0;

    if(bal < INT32_MIN )
    {
        printf("Failed!!!");
    }
    else
    {
        printf("Success!!!");
    }
    return 0;
}

条件if(bal < INT32_MIN )总是如此.这怎么可能?

如果我将宏更改为:

#define INT32_MIN        (-2147483648L)

有谁可以指出这个问题?



1> Lundin..:

这非常微妙.

程序中的每个整数文字都有一个类型.它具有哪种类型由6.4.4.1中的表格规定:

Suffix      Decimal Constant    Octal or Hexadecimal Constant

none        int                 int
            long int            unsigned int
            long long int       long int
                                unsigned long int
                                long long int
                                unsigned long long int

如果文字编号不能适合默认int类型,它将尝试下一个更大的类型,如上表所示.因此对于常规十进制整数文字,它就像:

尝试 int

如果它不适合,请尝试 long

如果它不适合,请尝试long long.

Hex文字表现不同!如果文字不能适合签名类型int,它将首先尝试unsigned int继续尝试更大的类型.请参阅上表中的差异.

所以在32位系统上,你的文字0x80000000是类型的unsigned int.

这意味着您可以-在文字上应用一元运算符而不调用实现定义的行为,就像溢出有符号整数时一样.相反,你将获得价值0x80000000,一个正值.

bal < INT32_MIN调用通常的算术转换,表达式的结果0x80000000从中unsigned int提升long long.该值0x80000000保留,0小于0x80000000,因此结果.

当您2147483648L使用十进制表示法替换文字时,编译器不会选择unsigned int,而是尝试将其放入a中long.此外,L后缀表示long 如果可能,您需要一个.如果你继续阅读6.4.4.1中提到的表,L后缀实际上有类似的规则:如果数字不适合所请求的内容long,而不是32位的话,编译器会给你一个long long它的位置很合适.


@ASH不要将源代码中的整数文字的十六进制表示与有符号数的基础二进制表示混淆.在源代码中编写的文字"0x7FFFFFFF"总是一个正数,但你的`int`变量当然可以包含最大值为0xFFFFFFFF的原始二进制数.
"...用-2147483648L替换文字你明确得到一个长号,这是签名的." 嗯,在一个32位的"long"系统`2147483648L`中,不适合`long`,所以它变成`long long`,_then_应用`-` - 或者我认为.
关于如何将一元`-`应用于无符号整数的解释可以稍微扩展一下.我一直假设(虽然幸运的是从不依赖于这个假设)无符号值会被"提升"为有符号值,或者可能是未定义的结果.(老实说,它应该是一个编译错误;` - 3u`甚至意味着什么?)
@ASH因为int可以拥有的最大数量是`0x7FFFFFFF`.亲自尝试:`#include printf("%X \n",INT_MAX);`
@ASH`ìntn= 0x80000000`强制从无符号文字转换为有符号类型.会发生什么取决于您的编译器 - 它是实现定义的行为.在这种情况下,它选择将整个文字显示为`int`,覆盖符号位.在其他系统上,可能无法表示类型并调用未定义的行为 - 程序可能会崩溃.如果你执行`int n = 2147483648;`那么你将得到完全相同的行为,因此它根本不与十六进制表示法相关.
"环绕"无符号数的行为由C++标准修复.它与2的补码无关(只与`sizeof(unsigned)`有关).你确定它在C中有所不同吗?
"相反,在二进制补码系统中," - 实际上,表示负数的系统不会影响无符号算术,无符号算术是用模运算定义的.在32位int的情况下,`-0x80000000`始终为`0x80000000`.

2> Bathsheba..:

0x80000000是一个unsigned值为2147483648 的文字.

对此使用一元减号仍会为您提供一个非零值的无符号类型.(事实上​​,对于非零值x,您最终得到的值是UINT_MAX - x + 1.)



3> Vlad from Mo..:

这个整数文字0x80000000有类型unsigned int.

根据C标准(6.4.4.1整数常数)

5整数常量的类型是相应列表中可以表示其值的第一个.

并且这个整数常量可以用类型表示unsigned int.

所以这个表达

-0x80000000具有相同的unsigned int类型.此外,它0x80000000在二进制补码表示中具有相同的值 ,计算以下方式

-0x80000000 = ~0x80000000 + 1 => 0x7FFFFFFF + 1 => 0x80000000

如果要编写,这会产生副作用

int x = INT_MIN;
x = abs( x );

结果将再次出现INT_MIN.

因此在这种情况下

bal < INT32_MIN

有比较0无符号的0x80000000转换长长整型根据通常的算术转换的规则输入.

很明显,0小于0x80000000.



4> dbush..:

数字常量0x80000000是类型unsigned int.如果我们采取-0x80000000并做2s恭维数学,我们得到这个:

~0x80000000 = 0x7FFFFFFF
0x7FFFFFFF + 1 = 0x80000000

所以-0x80000000 == 0x80000000.并且比较(0 < 0x80000000)(因为0x80000000是无符号的)是真的.



5> chux - Reins..:

在思考-数字常量的一部分时会出现混淆.

在下面的代码0x80000000是数字常量.它的类型仅在此确定.将-被应用之后并不会改变类型.

#define INT32_MIN        (-0x80000000)
long long bal = 0;
if (bal < INT32_MIN )

原始的未经修饰的数字常数是正面的.

如果是小数,然后被分配类型是将其持有第一类:int,long,long long.

如果常数是八进制或十六进制,它会保持它的第一种类型:int,unsigned,long,unsigned long,long long,unsigned long long.

0x80000000,在OP的系统上得到unsigned或的类型unsigned long.无论哪种方式,它都是一些无符号类型.

-0x80000000也是一些非零值并且是一些无符号类型,它大于0.当代码将其与a 进行比较时,比较的两侧long long不会改变,所以0 < INT32_MIN是真的.


另一种定义避免了这种奇怪的行为

#define INT32_MIN        (-2147483647 - 1)

让我们走在梦幻之地了一段时间,其中intunsigned48位.

然后0x80000000适合,int所以类型int. -0x80000000然后是负数,打印输出的结果是不同的.

[回到真实的话]

由于0x80000000在签名类型之前适合某些无符号类型,因为它比some_signed_MAX内部大some_unsigned_MAX,所以它是一些无符号类型.



6> haccks..:

C有一个规则,即整数文字可能是signedunsigned取决于它是否适合signedunsigned(整数提升).在一32台机器上,文字0x80000000将是unsigned.2的补充-0x800000000x80000000 在32位机器上.因此,比较bal < INT32_MIN是在比较之间signedunsigned之前,根据C规则unsigned int将转换为long long.

C11:6.3.1.8/1:

[...]否则,如果带有符号整数类型的操作数的类型可以表示具有无符号整数类型的操作数类型的所有值,则具有无符号整数类型的操作数将转换为操作数的类型.有符号整数类型.

因此,bal < INT32_MIN永远true.

推荐阅读
wangtao
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有