【问题标题】:uint16_t subtraction GCC compilation erroruint16_t 减法 GCC 编译错误
【发布时间】:2015-08-21 05:19:19
【问题描述】:

我有以下程序

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

【问题讨论】:

  • 你为什么要首先这样做?
  • 不要使用这些选项。

标签: c gcc integer-promotion uint16


【解决方案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 收到警告。

【讨论】:

  • 嗯,是的,16 位 int 会给出不同的结果。
【解决方案2】:

您的案例 B 相当于:

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

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

【讨论】:

  • 结果确实适合这段代码中的uint16_t,所以编译器很懒。
  • @MattMcNabb,请随时修复它。
  • @ams 毫无疑问,我将不得不与一群想要看到这个警告的人开战,即使它是假的
  • 我想这只是在持续传播发生之前发出警告。修复它可能需要更多的代码。
  • 以下所有优化选项都会产生同样的错误[O0, O1, O2, O3, Os]
猜你喜欢
  • 2012-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多