gcc隐含的常量符号

时间:2015-06-04 00:33:43

标签: c gcc signedness

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

strSQLPharmContact = "SELECT TOP 1 tbl_Contacts.ID, 
tbl_Contacts.idSite, tbl_Contacts.role, tbl_Contacts.name, 
tbl_Contacts.email, tbl_Contacts.phone, tbl_Contacts.involvement, 
tbl_Contacts.Taken" _ & "FROM tbl_Contacts " _
& "WHERE (((tbl_Contacts.role)= 'Pharmacist') AND 
((tbl_Contacts.involvement)=True) AND ((tbl_Contacts.Taken)=False)); "

当我编译上面的内容时,我得到了#define SPECIFIC_VALUE 0xFFFFFFFF //... int32_t value = SOMETHING; if (value == SPECIFIC_VALUE) { // Do something }

一切都很好 - 似乎gcc将十六进制常量解释为无符号,并且不喜欢与有符号整数的比较。但是,如果我将定义更改为warning: comparison between signed and unsigned integer expressions [-Wsign-compare]之类的内容,警告就会消失。再一次,我并不特别惊讶 - 符号位为零会使gcc更乐意将常量解释为有符号值。令我惊讶的是,如果我将定义更改为#define SPECIFIC_VALUE 0x7FFFFFFF,我仍然会收到警告。我希望明确告诉编译器将我的常量解释为有符号值会使警告静音。

1 个答案:

答案 0 :(得分:3)

关于应用于整数的转化,请阅读C11 §6.3.1.1 §6.4.4.1 ¶5指定为整数常量指定的类型。 gcc应该坚持这些规则。

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

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

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

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

#define UVALUE ((uint32_t)0x7FFFFFFF)

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