我正在使用K& R书来学习c语言。在第二章中,作者谈到了隐式转换。那本书说:
当涉及无符号操作数时,转换规则会更复杂。问题是 有符号值和无符号值之间的比较取决于机器,因为它们取决于各种整数类型的大小。例如,假设int是16位而long是32位。然后-1L< 1U,因为1U是unsigned int,被提升为有符号长整数。但是-1L> 1UL因为-1L被提升为无符号长,因此看起来是一个大的正数。
我在两种不同的场景中尝试了以下代码:
sizeof(-1L)
- >的位置8字节和sizeof(1U)
- > 4个字节sizeof(-1L)
- >的位置4字节和sizeof(1U)
- > 4个字节代码:
int main() {
if(-1L > 1U)
printf("true");
else
printf("false");
return 0;
}
结果:
false
true
所以我在每种情况下得到两个不同的OP。
正如作者所说,对于2个不同的数据大小,一个是16,另一个是32,它在我的x86-64情况下表现良好。
但我无法理解为什么在32位的第二种情况下,我得到true
。
正如作者所说,unsigned int
被提升为signed long int
,如果这是真的,那么两者都是
应该是4个字节宽,那么为什么打印true
而不是false
?现在两者都应该是signed long
。
正如作者所说它与机器有关,那么long
和int
都应该有相同的字节大小,那么隐式转换是如何发生的呢?
我的理解是-1
存储为两个补码,即 0xFFFFFFFF
> 0x1
所以在第二种情况下它应该是true
。
但这种解释与第一种情况相矛盾。
如果我认为错误,请纠正我,因为我不熟悉隐式转换。
有人可以解释一下这种行为吗?
答案 0 :(得分:3)
让我们首先解释排名系统
6.3.1 Arithmetic operand(c99 standard)
A) The rank of a signed integer type shall be greater than the rank of any signed integer
type with less precision(more bytes higher precision higher rank)
B) The rank of long long int shall be greater than the rank of long int, which shall be
greater than the rank of int, which shall be greater than the rank of short int, which
shall be greater than the rank of signed char.
C) The rank of any unsigned integer type shall equal the rank of the corresponding signed
integer type, if any.
(in other words if your system unsigned int is 32bits and your int is 32bits then the
ranks of these are the same.)
以上解释了排名。
现在进行算术转换。
6.3.1.8 Usual arithmetic conversions (c99 standard)
1)If both operands have the same type, then no further conversion is needed.
2)Otherwise, if both operands have signed integer types or both have unsigned integer
types, the operand with the type of lesser integer conversion rank is converted to the
type of the operand with greater rank.(similar to 1)
3)Otherwise, if the operand that has unsigned integer type has rank greater or equal to
the rank of the type of the other operand, then the operand with signed integer type is
converted to the type of the operand with unsigned integer type.
4)Otherwise, if the type of the operand with signed integer type can represent all of the
values of the type of the operand with unsigned integer type, then the operand with
unsigned integer type is converted to the type of the operand with signed integer type
5)Otherwise, both operands are converted to the unsigned integer type corresponding to the
type of the operand with signed integer type.
2)在x86 32bits平台上编译并执行。 sizeof(-1L) - > 4byte和sizeof(1U) - > 4个字节
在你的案例中查看陈述3& C.无符号值(4字节)的等级等于有符号值(4btyes),因此将有符号值转换为无符号值,当发生这种情况时,符号位使其看起来像一个非常大的值。 -1L> 1U因此是真的
1)在x86 64bits平台上编译并执行。 sizeof(-1L) - > 8byte和sizeof(1U) - > 4个字节
在这种情况下,无符号值等级小于有符号值的等级。看看4)。 有符号整数(8字节)可以表示任何4字节无符号值。因此,无符号4byte值被转换为有符号值。(这将保留符号位,符号位为0)
因此-1L> 1U是假的
答案 1 :(得分:2)
对于二进制算术和关系运算符:
如果任一操作数的类型为long double,则另一个操作数将转换为long double。否则,如果任一操作数的类型为double,则另一个操作数将转换为double。否则,如果任一操作数的类型为float,则另一个操作数将转换为float。否则,将对两个操作数执行整体促销。
(整数提升:char,short int或int位字段,或者它们的有符号或无符号变量,或者枚举类型,可以在任何可以使用int或unsigned int的表达式中使用。 int可以表示原始类型的所有值,该值将转换为int;否则将转换为unsigned int。)
然后,如果任一操作数的类型为unsigned long int,则另一个操作数将转换为unsigned long int。否则,如果一个操作数的类型为long int而另一个操作数的类型为unsigned int,则如果long int可以表示unsigned int的所有值,则unsigned int类型的操作数将转换为long int; 如果long int不能表示unsigned int的所有值,则两个操作数都将转换为unsigned long int。否则,如果任一操作数的类型为long int,则另一个操作数将转换为long int。否则,如果任一操作数的类型为unsigned int,则另一个操作数将转换为unsigned int。否则,两个操作数都具有int类型。
粗体的句子解释了你的第二种情况,其中long int与unsigned int具有相同的宽度,因此不能保存unsigned int的所有值。
(以上描述缺少类型unsigned long long int
和long long it
,但规则基本相同。)
答案 2 :(得分:2)
但我无法理解为什么在第二种情况下32位其OP - > true。正如作者所说,unsigned int被提升为signed long int,如果是这样,那么两者都是4字节宽,为什么它的打印为true而不是false。因为现在两人签了很长时间。
作者说,如果int
和long
的大小不同,则unsigned int
会提升为signed long
。
如果int
和long
的尺寸相同,那么long
太小,无法容纳unsigned int
的所有值,因此两者都会转换为unsigned long
答案 3 :(得分:0)
正如所有回答上述问题的人都是正确的,只是为了增加清晰度和我的理解写作,以便更清晰。
- > if one operand has type long int and the other has type unsigned int,
- > if a long int can represent all values of an unsigned int the operand of type unsigned int is converted to long int;
- > if a long int cannot represent all the values of an unsigned int, both operands are converted to unsigned long int.
所以从上面one operand has type long int
,-1L
和the other has type unsigned int
,1U
假设-1L的大小为---> 8byte
且1U的大小为4 byte
0X0000-0XFFFFF values can be represented using in long int whose sizeof is 8 byte
所以在这种情况下long int can represent all values of an unsigned int
,即使用8byte --->它可以代表所有值unsigned int 1U
。
所以---->这里operand of type unsigned int is converted to long int
---> -1L > 1U --> is false
即将来临的第二个案例
if a long int cannot represent all the values of an unsigned int
即sizeof -1L -->4byte
和sizeof 1U -->4byte
这里long int不能表示所有值,即使用4个字节 - >它cannot represent
unsigned int 1U的所有值。所以两个操作数都是converted to unsigned long int
-1L似乎是较大的值,因为它现在与1U相比无符号。
i.e---->0xFFFFFFFF > 0x1 ---> its true