3

我正在尝试减去两个无符号整数并将结果与​​有符号整数(或文字)进行比较。使用unsigned int类型时,行为符合预期。使用uint16_t(from 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 中?如果我将输出更改1010U0,这似乎支持这一点(如果减法结果存储为 int 并且与 unsigned int 进行比较,则减法结果将转换为 unsigned int)。

4

2 回答 2

7

因为计算不是使用低于 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”。

于 2012-04-06T18:59:34.813 回答
5

在执行-and<操作之前,会应用一组称为通常算术转换的转换来将操作数转换为通用类型。作为此过程的一部分,将应用整数提升,它将类型提升为比这两种类型中的一种更窄int或更窄unsigned int的类型。

在第一种情况下, 和 的类型abunsigned int因此不会由于-运算符而发生类型更改 - 结果是unsigned int具有大正值的 an UINT_MAX - 14。然后,因为intunsigned int具有相同的排名,所以10类型为 的值int被转换为unsigned int,然后执行比较,得到值0

在第二种情况下,很明显,在您的实现中,类型int可以保存 type 的所有值uint16_t。这意味着当应用整数提升时,a和的值b被提升为 type int。执行减法,得到-15type的值int。的两个操作数<都已经是int,因此不执行任何转换;的结果<1

在后一种情况下使用 a10U时,结果a - b仍然-15是 type int。然而,现在,通常的算术转换导致这个值被转换为unsigned int(就像10第一个例子中的那样),这导致值UINT_MAX - 14; 的结果<0

于 2012-04-07T12:36:00.187 回答