1

我有以下程序

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

4

2 回答 2

1

您的案例 B 相当于:

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

结果是intwhich may not fit in uint16_t,因此,根据您的极端警告选项,它会产生警告(因此会产生错误,因为您将警告视为错误)。

于 2015-08-20T21:02:54.037 回答
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 手册:

-W转换

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

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

于 2015-08-20T21:19:19.877 回答