我正在尝试将两个无符号整型数相减,并将结果与有符号整型数(或文本)进行比较。当使用unsigned int
类型时,行为与预期一致。当使用uint16_t
(来自stdint.h
)类型时,行为与预期不一致。比较是使用gcc 4.5完成的。
给定以下代码:
unsigned int a;
unsigned int b;
a = 5;
b = 20;
printf("%u\n", (a-b) < 10);
输出是0,这是我所期望的。a和b都是无符号的,并且b大于a,所以结果是一个大于10的大无符号数。现在,如果我将a和b改为uint16_t类型:
uint16_t a;
uint16_t b;
a = 5;
b = 20;
printf("%u\n", (a-b) < 10);
输出为1。为什么会这样?两个uint16_t类型之间的减法结果是否存储在gcc的int中?如果我将10
更改为10U
,输出仍为0,这似乎支持这一点(如果减法结果存储为int,并且与无符号int进行比较,则减法结果将转换为无符号int)。
4条答案
按热度按时间fdbelqdn1#
因为计算不是用int / unsigned int以下的类型完成的(char、short、unsigned short等;但不是long、unsigned long等),但它们首先被提升为int或unsigned int中的一个。“uint16_t”在您的实现中可能是“unsigned short,”在您的实现中被提升为“int”。因此,该计算的结果是“-15,"小于10。
在使用16位进行计算的较早实现中,“int”可能无法表示“unsigned short”的所有值,因为两者具有相同的位宽。此类实现必须将“unsigned short”提升为“unsigned int”。在此类实现中,比较结果为“0”。
tag5nh1u2#
在执行
-
和<
运算之前,会套用一组称为 * 一般算术转换 * 的转换,将算子转换为一般型别。在此程序中,会套用 * 整数提升 *,将比int
或unsigned int
窄的型别提升为这两种型别之一。在第一种情况下,
a
和b
的类型是unsigned int
,因此不会因-
运算符而发生类型更改-结果是unsigned int
,具有较大的正值UINT_MAX - 14
。然后,由于int
和unsigned int
具有相同的秩,将类型为int
的值10
转换为unsigned int
,然后执行比较,从而得到值0
。在第二种情况下,很明显,在您的实现中,
int
类型可以保存uint16_t
类型的所有值。这意味着,当应用整数提升时,a
和b
的值将提升为int
类型。执行减法,从而产生类型为int
的值-15
。<
的两个操作数都已经是int
,因此不执行任何转换;<
的结果是1
。当您在后一种情况下使用
10U
时,a - b
的结果仍然是-15
,类型为int
。但是,现在,通常的算术转换会将此值转换为unsigned int
(就像第一个示例中的10
一样),从而得到值UINT_MAX - 14
;<
的结果是0
。jdg4fx2g3#
[...]否则,对两个操作数都执行整数提升。
4jb9z9bj4#
当
uin16_t
是int
的子范围时,使用int
数学来执行(a-b) < 10
。使用一个
unsigned
常量将左边轻轻移动到unsigned
math.(a - b) < 10u
也适用于这个简单的代码,但是我建议的想法是将双方都作为unsigned
数学来执行,因为更复杂的代码可能需要这样做。