C编程。无符号整数评估问题

时间:2018-02-03 15:42:08

标签: c

在C编程中我遇到了这个问题:

int v = 0XFFFD;
unsigned z=1;

评估表达式:

a) (v+1)/2  
b) -1 > z

在问题书中,为 a)答案是-1,而答案是 b)答案是1

任何人都可以解释原因吗? 因为在我看来为 a)我认为答案是32767,而对于 b)是0

4 个答案:

答案 0 :(得分:3)

案例1: 默认情况下,int的类型是有符号的,这意味着编译将检查符号位,如果符号位为1则意味着输出将为负。

int v = 0XFFFD

v如何存储在内存中,如果它有一个小端,如下所示

    -------------------------
    | 1111 1111  | 1111 1101 |
    -------------------------
   MSB                      LSB
                             v

正如你所看到的那样,符号位(第15位,如果是短整数)是1,负数存储在内存中作为两个赞美。以及v i的两个赞美

 one's compliment =>  0000 0000 |  0000 0010
                                          +1
                      -----------------------
                      0000 0000 |  0000 0011 => 3 and since sign bit is one  that's why v is -3 

当您执行(v+1)/2 == (-3+1)/2 => -1

案例2:

unsigned z = 1;

让我们说声明看起来像

printf("%d\n", -1 > z);

这里在执行两个操作数之间的任何操作时,您应该了解操作数类型是否不同的后果。

 -1  >  z
 |      |           => comparing different operands
signed unsigned       (one is signed and other one unsigned) => Implicit type conversion will happen i.e implicitly signed gets promoted into unsigned by compiler)
                            ||
                        65535 > 1 => true => pints 1 
                        |
               (-1 is signed and its converted into unsigned and unsigned equivalent of -1 is 65535 in case of shot integer)

答案 1 :(得分:1)

C在功能上定义其整数数学运算,而不是位模式。考虑一个位数可能很有用,但让我们看看C指定的内容。

int v = 0XFFFD;

int必须至少编码[-32767 ... 32767]。 OP的案例似乎使用了最小尺寸的int

0XFFFD十六进制常量,值为65,533。它的类型是第一个适合:int, unsigned, long, unsigned long ...。在这种情况下,它是unsigned

int v = some_unsigned需要将unsigned转换为int。当源超出int范围时,实现已定义会发生什么。一个常见的结果是"环绕"通过减去2 16 。代码可以改为分配INT_MAX。它是实现定义。显然代码包含在OP的案例中。

int v = 65533 - 65536; // -3
// or maybe
int v = 32767; // Uncommon implementation defined result.

(v+1)/2只是(-3 + 1)/2 - > -1

如果十六进制常量适合int,可能在32位int的平台上,(65533 + 1)/2将被考虑为32767 OP。

unsigned z = 1;很简单。 z的值为1.

-1 > zint -1unsigned进行比较。比较使用相同的类型。

unsigned 等级高于int,因此-1会转换为unsigned,并通过添加{{1}来更改其值}}。 UINT_MAX +1 - > -1 + UINT_MAX +1

现在比较就像UINT_MAX,这是真的。比较结果为UINT_MAX > 1,0或1.此结果为int 1。

结果与int的范围无关。

答案 2 :(得分:0)

  1. 因为int是有符号整数,0xfffd等于-3。所以(v+1)/2获得-1
  2. 有符号整数自动转换(强制)为无符号整数 如果你将有符号整数与无符号整数进行比较。

答案 3 :(得分:0)

短篇小说:你的书看起来很糟糕。

永远不要初始化int(带符号的类型),其值可以是无符号的,例如十六进制常量。

长篇故事

“1”的结果取决于很多事情。首先,知道int的有效位数是很重要的。在下面让我们假设它是16位,否则问题更加无意义。

如果是16,则右侧的十六进制常量大于最大int。由于C中的整数常量总是正数,因此它不适合int,因此它具有类型unsigned int

因此,必须为初始化转换unsignedint。这是“实现定义”,只要记录在案,您的编译器就可以执行所需的操作。

许多编译器执行“延迟”转换,也就是说,他们只选择具有与unsigned值相同的表示的值。如果您的计算机有int的两个表示(同样是依赖于实现的选项),则结果将是负值,很可能是-3

所以,“1”的真正答案是:它取决于。介绍性书籍不应该以这种方式提出问题,只是建议该操作的结果取决于整数表示。整数表示只是偶然出现。