【问题标题】:gcc implicit signedness of constantsgcc 常量的隐含符号
【发布时间】:2015-06-04 00:33:42
【问题描述】:

我在 gcc 对常量符号的解释中遇到了一些有趣的行为。我有一段代码(大大简化)如下所示:

#define SPECIFIC_VALUE 0xFFFFFFFF

//...

int32_t value = SOMETHING;
if (value == SPECIFIC_VALUE) {
    // Do something
}

当我编译上述内容时,我得到了warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

一切都好——似乎 gcc 将十六进制常量解释为无符号,并且不喜欢与有符号整数进行比较。但是,如果我将定义更改为 #define SPECIFIC_VALUE 0x7FFFFFFF 之类的东西,警告就会消失。同样,我并不感到特别惊讶——符号位为零会使 gcc 更乐意将常量解释为有符号值。真正让我吃惊的是,如果我将定义更改为#define SPECIFIC_VALUE INT32_C(0xFFFFFFFF),我仍然会收到警告。我希望明确告诉编译器将我的常量解释为有符号值会使警告静音。

【问题讨论】:

  • 没有int32_t 可以等于0xFFFFFFFF。如果你想要-1,写-1
  • INT32_C(X) 不在 ISO C 中,但应该将 int32 的整数后缀应用到 X。这不是演员表。在具有 32 位 int 的系统上,32 位 int 将没有后缀,因此此宏对参数没有影响。
  • @Matt McNabb INT32_C(X) 在 C11“最小宽度整数常量的宏”第 7.20.4.1 节 1
  • @chux 太酷了。我在 inttypes.h 下查找,但结果发现它在 stdint.h 中

标签: c gcc signedness


【解决方案1】:

阅读C11 §6.3.1.1了解应用于整数的转换。 §6.4.4.1 ¶5 指定给定整数常量的类型。 gcc 应该遵守这些规则。

十六进制常量实际上是无符号的(按标准)int(假设为 32 位整数)。所以这符合而不是偶然!

如果您清除 MSbit,则常量可以表示为(有符号)int,但是。所以比较顺利。仍然是标准的。

第三条消息缺少INT32_C 的定义,所以我无能为力。但我认为你现在可以自己解决这个问题。请记住,在 `#define' 中无法检测到错误,只有在宏展开后才能检测到。

如果你真的想要unsigned,一般规则是将U 添加到常量(是的,也适用于十六进制)。或者转换常量:

#define UVALUE ((uint32_t)0x7FFFFFFF)

这里会更好,因为它实际上并不依赖于int 的大小。

【讨论】:

  • @iharob:谢谢。每个人的做法似乎都不一样。
  • ((int32_t)0xFFFFFFFF) 溢出,因为int32_t 的最大值是0x7FFFFFFF。该值可能将是-1,但严格来说它是实现定义的。
  • 是的,我刚试过。其实应该听我自己的建议。我只对无符号使用十六进制,这是我的错误:坚持你的模式。已编辑(是的:这两项更改都是有意的)。
  • 好的,现在应该没问题了。
  • 许多编译器如果不在符合标准的模式下调用,就会使用不同的整数文字规则
猜你喜欢
  • 2015-10-18
  • 2012-03-01
  • 2011-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多