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
的大小。
我在 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
的大小。