gcc 常量的隐式符号

gcc implicit signedness of constants

我在 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),我仍然会收到警告。我希望明确告诉编译器将我的常量解释为带符号的值会使警告消失。

Read C11 § 6.3.1.1 about the conversions applied to integers. § 6.4.4.1 ¶5 指定整数常量的类型。 gcc 应该遵守这些规则。

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

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

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

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

#define UVALUE ((uint32_t)0x7FFFFFFF)

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