在C编程中我遇到了这个问题:
int v = 0XFFFD;
unsigned z=1;
评估表达式:
a) (v+1)/2
b) -1 > z
在问题书中,为
a)答案是-1
,而答案是
b)答案是1
。
任何人都可以解释原因吗?
因为在我看来为
a)我认为答案是32767
,而对于
b)是0
。
答案 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 > z
将int
-1
与unsigned
进行比较。比较使用相同的类型。
unsigned
等级高于int
,因此-1
会转换为unsigned
,并通过添加{{1}来更改其值}}。 UINT_MAX +1
- > -1 + UINT_MAX +1
。
现在比较就像UINT_MAX
,这是真的。比较结果为UINT_MAX > 1
,0或1.此结果为int
1。
结果与int
的范围无关。
答案 2 :(得分:0)
int
是有符号整数,0xfffd等于-3。所以(v+1)/2
获得-1 答案 3 :(得分:0)
短篇小说:你的书看起来很糟糕。
永远不要初始化int
(带符号的类型),其值可以是无符号的,例如十六进制常量。
长篇故事:
“1”的结果取决于很多事情。首先,知道int
的有效位数是很重要的。在下面让我们假设它是16位,否则问题更加无意义。
如果是16,则右侧的十六进制常量大于最大int
。由于C中的整数常量总是正数,因此它不适合int
,因此它具有类型unsigned int
。
因此,必须为初始化转换unsigned
到int
。这是“实现定义”,只要记录在案,您的编译器就可以执行所需的操作。
许多编译器执行“延迟”转换,也就是说,他们只选择具有与unsigned
值相同的表示的值。如果您的计算机有int
的两个表示(同样是依赖于实现的选项),则结果将是负值,很可能是-3
。
所以,“1”的真正答案是:它取决于。介绍性书籍不应该以这种方式提出问题,只是建议该操作的结果取决于整数表示。整数表示只是偶然出现。