【问题标题】:How to type cast a literal in C如何在 C 中键入转换文字
【发布时间】:2009-09-01 13:13:35
【问题描述】:

我有一个小样本函数:

#define VALUE 0

int test(unsigned char x) {
  if (x>=VALUE)
    return 0;
  else
    return 1;
}

我的编译器警告我,比较 (x>=VALUE) 在所有情况下都是正确的,这是正确的,因为 x 是一个无符号字符并且 VALUE 定义为值 0。所以我将代码更改为:

if ( ((signed int) x ) >= ((signed int) VALUE ))

但是警告又来了。我用三个 GCC 版本(所有版本 > 4.0,有时您必须启用 -Wextra)对其进行了测试。

在改变的情况下,我有这个显式转换,它应该是一个有符号的 int 比较。为什么它声称比较总是正确的?

【问题讨论】:

  • 那么,你想要完成什么?在什么情况下你希望它返回 1 而不是 0?
  • 我的目的是避开这个警告。
  • 不要逃避警告,试着摆脱你需要知道无符号是否 >= 0。它总是 - 这就是编译器告诉你的。
  • 我希望有可能将VALUE的定义更改为0以外的其他值。如果VALUE不是0,没问题。
  • 听起来是向我应用 YAGNI 的好时机。等到您真正需要该功能。或者,如果您确实需要它,它可能不应该是编译时间常数,而是配置参数或命令行参数或您拥有的任何东西。

标签: gcc casting literals gcc-warning


【解决方案1】:

即使使用强制转换,在所有已定义行为的情况下,比较仍然是正确的。编译器仍然确定 (signed int)0 的值为 0,并且如果您的程序已定义行为,则仍然确定 (signed int)x) 为非负数(如果值超出有符号类型的范围,则从无符号转换为有符号是未定义的) .

因此编译器继续警告,因为它继续完全消除 else 情况。

编辑:要使警告静音,请将您的代码编写为

#define VALUE 0

int test(unsigned char x) {
#if VALUE==0
  return 1;
#else
  return x>=VALUE;
#endif
}

【讨论】:

  • unsigned char永远不能超出signed int 的范围。即使设置了符号位,该值也很好地在signed int 的范围内,并且操作始终是明确定义的(并且结果始终为正)。
  • 糟糕,我错过了它是从 char 到 int。不过,这可能发生在 sizeof(int)==1 的 C 的(理论)实现上。鉴于 int 必须至少有 2 个八位字节,这在一个 char 也是两个八位字节的实现上是可能的。我同意在现实平台上,这里不会发生溢出。
  • @Martinv.Löwis:一些实际的字寻址 DSP 在其 C 实现中具有 char = int = 32 位。
【解决方案2】:

xunsigned char,表示它介于 0 和 256 之间。由于 int 大于 char,因此将 unsigned char 转换为 signed int 仍然保留 chars 的原始值.由于此值始终 >= 0,因此您的 if 始终为真。

【讨论】:

    【解决方案3】:

    unsigned char 的所有值都可以在您的int 中完美匹配,因此即使使用演员表,您也永远不会得到负值。您需要的演员表是signed char - 但是,在这种情况下,您应该在函数签名中将x 声明为signed。向客户撒谎说您需要一个未签名的值,而实际上您需要一个签名的值是没有意义的。

    【讨论】:

      【解决方案4】:

      VALUE0#define 表示您的功能简化为:

      int test(unsigned char x) {
        if (x>=0)
          return 0;
        else
          return 1;
      }
      

      由于x 始终作为unsigned char 传入,因此无论您将x0 转换为@987654331,它的值始终介于0255 之间@ 在if 语句中。因此,编译器会警告您 x 将始终大于或等于 0,并且永远无法到达 else 子句。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-17
        • 2015-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多