uint16_t减法GCC编译错误

uint16_t subtraction GCC compilation error

我有以下程序

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>

int main(void) {
    uint16_t o = 100;
    uint32_t i1 = 30;
    uint32_t i2 = 20;

    o = (uint16_t) (o - (i1 - i2)); /*Case A*/
    o -= (uint16_t) (i1 - i2);      /*Case B*/
    (void)o;
    return 0;
}

案例 A 编译没有错误。
情况B导致以下错误
[error: conversion to ‘uint16_t’ from ‘int’ may alter its value [-Werror=conversion]]

我使用的警告选项是:
-Werror -Werror=strict-prototypes -pedantic-errors -Wconversion -pedantic -Wall -Wextra -Wno-unused-function

我在 Ubuntu 15.04 64 位上使用 GCC 4.9.2。

为什么我在 案例 B 中出现此错误,但在 案例 A 中却没有?

PS: 我 运行 使用 clang 编译器的相同示例,两种情况都可以正常编译。

您的案例 B 相当于:

o = o - (uint16_t) (i1 - i2);      /*Case B*/

结果是 int,可能不适合 uint16_t,因此,根据您的极端警告选项,它会产生警告(因此会产生错误,因为您将警告视为错误).

整数提升是个奇怪的东西。基本上,任何较小尺寸的所有整数值都会提升为 int 以便可以有效地对其进行操作,然后在存储时将其转换回较小的尺寸。这是 C 标准规定的。

所以,案例 A 真的是这样的:

o = (uint16_t) ((int)o - ((uint32_t)i1 - (uint32_t)i2));

(请注意,uint32_t 不适合 int,因此无需推广。)

而且,案例 B 确实是这样的:

o = (int)o - (int)(uint16_t) ((uint32_t)i1 - (uint32_t)i2);

主要区别在于案例 A 具有显式转换,而案例 B 具有隐式转换。

来自 GCC 手册:

-Wconversion

Warn for implicit conversions that may alter a value. ....

因此,只有案例 B 会收到警告。