uint16_t减法GCC编译错误

时间:2015-08-20 20:47:58

标签: c gcc integer-promotion uint16

我有以下程序

#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编译器运行相同的示例,并且两种情况都编译得很好。

2 个答案:

答案 0 :(得分:1)

您的案例B相当于:

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

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

答案 1 :(得分:1)

整数促销是一件奇怪的事情。基本上,任何较小尺寸的所有整数值都会提升为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

     

警告可能会改变值的隐式转换。 ....

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