6

我正在尝试运行以下代码,但对这里发生的事情感到困惑:

int main()
{
 /* 
    a = -1; 
    b = 0xffffffff; 
 */
if(-1 == 0xffffffff )
        printf("-1 is equal to maximum\n");
else
        printf(" -1 is not equal to maximum\n");

if(0xff < -1)
        printf(" Less than -1 \n");
if(0xff < 0xffffffff)
        printf(" Less than maximum\n");

我也尝试使用注释部分并将 -1 替换为“a”,将 0xffffffff 替换为“b”,但结果相同。

它是 32 位系统,所以我采用了 4 字节的整数大小。

我的输出是:

-1 is equal to maximum
 Less than maximum

如果 -1 等于最大值,那么它应该执行最后两个 if 语句。但它没有发生。为什么?

4

4 回答 4

5

我将从 C++ 中引用它;我认为C也是一样的:

字面-1量始终是 a signed int

文字0xff是 a signed int,但是0xffffffff是 a unsigned int

在混合符号的比较中,两个操作数都被转换为无符号,解释了你的所有结果。

以下是 C++11 表 6 中关于裸整型字面量(即没有类型后缀)的类型的规则:

  • 十进制文字是int,long int或中最小的类型long long int,以适合者为准。

  • 十六进制文字是int, unsigned int, long int, unsigned long int, long long int,中最小的类型unsigned long long int,以适合者为准。

再次拼写出来:

  • 在您的第一次比较中,双方都转换为unsigned int,给出值0xFFFFFFFF

  • 在第二个比较中,两项都是有符号整数,左项是255,右项是-1

  • 在第三次比较中,两项都转换为unsigned int


请注意,对于这个问题,我们从来不需要担心签名的硬件实现。唯一相关的与平台相关的值是 的大小int,我们在断言0xffffffff不适合 aint确实适合 时使用该值unsigned int

于 2012-09-10T12:04:02.697 回答
3

在 C/C++ 中,负数以 2 的补码格式存储,最高有效位 (MSB) 用作叹息指示。

MSB 1 表示-ve,MSB 0 表示+ve。1xxxxxxxxxx 是 -ve 数字,0xxxxxxxxxx 表示 +ve。在 1xxxxxxx 中,“xxxxxx”是 2 对数字的补语。在 0xxxxxx 中,“xxxxx”是数字的实际二进制表示。

如果 MSB(符号位)为 1,编译器将数字解释为 -ve,并且理解数字必须是两者的补码。

首先让我们看看 2 的恭维是什么:

2 的恭维是否定一个实际的数字(所有位),然后加 1。

十进制 1 = 00000001

~ 十进制 1 = 11111110

2 的十进制补码 1 = 11111111(F 十六进制)

所以 -1 变成 = (1) 111111111111111

(1)是一个 MSB,表示 -ve 数,其余的是 2 的补码。

因此-1 = 0xFFFFFFFF

您可以尝试打印一些 -ve 数字的二进制表示并比较数字的二进制表示的 2 的补码。

于 2014-11-11T07:51:55.213 回答
0

0xffffffff等于,-1因为该int类型只有四个字节,而 的二补码在内存中 ( -1) 。所以编译器无法区分- 内存中根本没有空间。0xffffffff-1 == (~1) + 1-10xffffffff

0x000000ff等于255which is 大于-1,所以最后两个ifs 不会被执行。

可能让您感到困惑的是:

char c = 0xff;
if( c == -1 ) {
     printf("char 0xff is -1");
}

在这种情况下,我将 achar与 an进行比较int,因此编译器将不得不扩展 8 位char类型。由于char已签名,符号(最高位)将被保留,您将得到-1(int)。

键盘上的交互式演示

这是一个示例,为什么在混合有符号/无符号类型和不同宽度的类型时需要小心。

于 2012-09-10T12:06:06.530 回答
0

首先,您看到的结果与有符号整数的位表示无关,尽管它们确实与大小有关。

当转换为无符号时,该值-1将转换为目标类型的最大值。这就是为什么-1 == 0xffffffff。的位表示-1不影响任何事情。

0xff < -1是假的,因为这两个值都是有符号int的:左边是 255,右边是 -1。

最后,在第一次比较中将 -1 转换为无符号的原因是这对于您的实现0xffffffff来说太大了(对于大多数实现来说也是如此)。但是,它确实适合(同样适用于您的实现,以及除 16 位机器之外的大多数实现)。为了将无符号整数与有符号整数进行比较,C 将有符号整数转换为无符号整数。这给出了令人惊讶的结果(包括令人惊讶的 -1 不知何故等于一个正数),这就是为什么大多数样式指南告诉您避免混合有符号和无符号类型的原因。但是改变语言已经太晚了。int unsigned int

于 2012-09-10T12:14:40.313 回答