我一直在阅读 K&R 的C 编程语言一书,并发现了这一点。
涉及无符号操作数时,转换规则更加复杂。问题 有符号和无符号值之间的比较是依赖于机器的,因为 它们取决于各种整数类型的大小。例如,假设 int 为 16 位,long 为 32 位。然后-1L < 1U,因为1U是一个无符号整型,被提升为有符号长整型。但是-1L > 1UL因为-1L被提升为unsigned long因此出现 是一个很大的正数。
从我开始学习 C 开始,我对这个无符号和有符号值没有什么困难。任何人都可以通过示例解释如何将无符号值转换为有符号值,反之亦然。
最佳答案
您已经通过积分提升接触了常见算术转换的表面(较新的标准使用术语整数提升)。
这些常见的算术转换是什么?
一般来说,当你有表达式时,涉及算术或逻辑运算符并且操作数不匹配,那么它们需要统一(正如我们所说的提升)为通用形式。在C90中,整数操作数之间的规则(为了简单起见,我故意跳过“低于”int
类型的规则)采用以下分级(请注意,C90中没有long long int
类型):
int
→ unsigned int
→ long int
→ unsigned long int
但是,unsigned int
之间有一个异常(exception)和long int
。如果它们具有相同的大小(以位为单位),则此类类型的两个操作数都将提升为公共(public)类型 unsigned long int
。在任何其他情况下,常见类型是位于右侧的类型(例如,当您有 int
和 unsigned int
操作数时,第一个将提升为 unsigned int
)。如果两个操作数具有相同的类型,则不会对上面列出的类型进行提升。
这与 -1L < 1U
有什么关系和-1L > 1UL
?
在您的情况下,假设 sizeof(int) == 16
和sizeof(long) = 32
,所以对于:
-
-1L < 1U
第二个操作数提升为long int
-
-1L > 1UL
第一个操作数提升为unsigned long
在前面的示例中,表达式的值为 1
如-1L < 1L
。在后一种情况下-1L
通过重复加或减,提升为无符号类型 n+1
,当 n
是 unsigned long
类型的最大值(在您的情况下 n+1 == 2^32
),它会产生大量(即 2^32-1
),因此整个表达式的值为 1
(类型 int
)也是如此。
关于清晰度 -1L < 1U 和 -1L > 1UL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25054477/