gcc中的C:uint16_t减法行为

huus2vyu  于 2022-11-13  发布在  其他
关注(0)|答案(4)|浏览(393)

我正在尝试将两个无符号整型数相减,并将结果与有符号整型数(或文本)进行比较。当使用unsigned int类型时,行为与预期一致。当使用uint16_t(来自stdint.h)类型时,行为与预期不一致。比较是使用gcc 4.5完成的。
给定以下代码:

  1. unsigned int a;
  2. unsigned int b;
  3. a = 5;
  4. b = 20;
  5. printf("%u\n", (a-b) < 10);

输出是0,这是我所期望的。a和b都是无符号的,并且b大于a,所以结果是一个大于10的大无符号数。现在,如果我将a和b改为uint16_t类型:

  1. uint16_t a;
  2. uint16_t b;
  3. a = 5;
  4. b = 20;
  5. printf("%u\n", (a-b) < 10);

输出为1。为什么会这样?两个uint16_t类型之间的减法结果是否存储在gcc的int中?如果我将10更改为10U,输出仍为0,这似乎支持这一点(如果减法结果存储为int,并且与无符号int进行比较,则减法结果将转换为无符号int)。

fdbelqdn

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”。

tag5nh1u

tag5nh1u2#

在执行-<运算之前,会套用一组称为 * 一般算术转换 * 的转换,将算子转换为一般型别。在此程序中,会套用 * 整数提升 *,将比intunsigned int窄的型别提升为这两种型别之一。
在第一种情况下,ab的类型是unsigned int,因此不会因-运算符而发生类型更改-结果是unsigned int,具有较大的正值UINT_MAX - 14。然后,由于intunsigned int具有相同的秩,将类型为int的值10转换为unsigned int,然后执行比较,从而得到值0
在第二种情况下,很明显,在您的实现中,int类型可以保存uint16_t类型的所有值。这意味着,当应用整数提升时,ab的值将提升为int类型。执行减法,从而产生类型为int的值-15<的两个操作数都已经是int,因此不执行任何转换; <的结果是1
当您在后一种情况下使用10U时,a - b的结果仍然是-15,类型为int。但是,现在,通常的算术转换会将此值转换为unsigned int(就像第一个示例中的10一样),从而得到值UINT_MAX - 14; <的结果是0

jdg4fx2g

jdg4fx2g3#

[...]否则,对两个操作数都执行整数提升。

4jb9z9bj

4jb9z9bj4#

uin16_tint的子范围时,使用int数学来执行(a-b) < 10
使用一个unsigned常量将左边轻轻移动到unsigned math.

  1. // printf("%u\n", (a-b) < 10);
  2. printf("%d\n", (0u + a - b) < 10); // Using %d as the result of a compare is int.
  3. // or to quiet some picky warnings
  4. printf("%d\n", (0u + a - b) < 10u);

(a - b) < 10u也适用于这个简单的代码,但是我建议的想法是将双方都作为unsigned数学来执行,因为更复杂的代码可能需要这样做。

相关问题