代码之家  ›  专栏  ›  技术社区  ›  101010

在C中减去无符号整数并获取-Wconversion警告

gcc c
  •  4
  • 101010  · 技术社区  · 6 年前

    uint16_t x;
    uint16_t y;
    
    y = 0;
    x = y - 1;
    

    See other SO articles for the "why" and to learn about 2's compliment .

    如果打开gcc标志-Wconversion,上面这个完全有效的C代码将抛出 conversion to ‘uint16_t {aka short unsigned int}’ from ‘int’ may alter its value 这是编译器试图帮助我们不陷入困境。我倾向于在程序中打开这样的警告,因为它们可以帮助我避免混乱。

    但是,有些实际情况下,我们可能会使用无符号int作为计数器,并希望减去1,而不获得此警告。另外,我们想把它当作计数器,把它降到零,然后停下来。要在C语言中做这件事,我们必须开一张支票。但是,这种检查代码将违反gcc警告。

    我想要我的蛋糕,我也想吃。

    3 回复  |  直到 6 年前
        1
  •  8
  •   Kitten    6 年前

    显式转换 y-1 uint16_t . GCC抱怨的不是减法,而是在将表达式的结果赋给(现在更小的)类型之后,可能会丢失信息。(整数操作数在表达式中使用时会自动提升为int,此时类型较小,并且可以在不损失精度的情况下容纳有符号的int。)

        2
  •  5
  •   Andrew Henle    6 年前

    在这个代码中

    x = y - 1;
    

    论据 y "default integer promotion" 按照C标准。

    那意味着 y - 1 int 价值,然后 内景 uint16_t 通过截断。这就是海合会所抱怨的。

    uint16_t :

    x = ( uint16_t ) ( y - 1 );
    

    6.3.1.1 Boolean, characters, and integers :

    • 即使两个有符号整数类型具有相同的表示,它们也不应具有相同的秩。
    • long long int的秩应大于long int的秩,long int的秩应大于 大于短整数的秩,该秩应大于
    • 任何无符号整数类型的秩应等于相应的有符号整数类型的秩(如果有)。
    • 任何标准整数类型的秩应大于具有相同宽度的任何扩展整数类型的秩。
    • 字符的等级应等于有符号字符和无符号字符的等级。
    • 任何扩展有符号整数类型相对于另一个具有相同精度的扩展有符号整数类型的秩为 实现已定义,但仍受 确定整数转换秩。

    可以使用int:

    • 整数类型(除int或unsigned int之外)的对象或表达式,其整数转换秩小于或等于 整数和无符号整数的秩。

    如果int可以表示原始类型的所有值(受限 否则,它将转换为无符号int 促销。

    整数促销保留包括符号的值。如前所述 在前面,是否将“普通”字符视为有符号字符

        3
  •  3
  •   dbush    6 年前

    表达式:

    x = y - 1;
    

    受到 C standard

    在表达式中,当int或unsigned

    • 整数类型(除int或unsigned int之外)的对象或表达式,其整数转换秩小于或等于 整数和无符号整数的秩。

    如果int可以表示原始类型的所有值(受 宽度,对于位字段),值转换为int; 否则,它将转换为无符号int 促销。

    y 属于类型 uint16_t ,其级别低于 int ,它被提升为 内景 内景 ,因此 y - 1 属于类型 内景 . 然后将该值分配给 uint16_t 等级低于 ,这就是你收到警告的原因。

    你需要把整个右手边 uint16_t 为了避免警告:

    x = (uint16_t)(y - 1);
    

    请注意,仅转换 - 内景 在表达式中使用。