我有以下代码。
uint32_t reg_val = 0;
uint64_t val = 0;
reg_val = 0;
reg_val = ((val & 0xffffff000000) >> 24);
dev_write(rw,reg_val);
编译器发出一条警告
warning: integer constant is too large for "long" type
我只将24位分配给reg_val,它被定义为大小为32位的无符号整数。
为什么编译器会生成此警告?
答案 0 :(得分:8)
常量0xffffff000000
对于32位长而言太大,在您的情况下范围为0x7fffffff
。
将其写为0xFFFFFF000000ULL
(unsigned long long
)
或者通过写作来避免这个问题
reg_val = (val >> 24) & 0xFFFFFF;
答案 1 :(得分:1)
稍微扩展greggo的答案。
如何定义整数文字取决于我们所使用的语言版本。
在C99中,整数文字自动具有可以包含其值的类型(除非不存在此类型)。因此,假设32位long
,则此常量已经具有类型unsigned long long
,因此不应发生警告。
我没有C89文本的副本,但C89没有long long
。如果规则相似,那么将会以实现定义的方式将常量转换为32位unsigned long
(可能会截断更高的位)。
由于OP收到了警告,但也能够使用ull
后缀来解决它,这表明他正在使用编译器扩展。从理论上讲,如果编译器以类似C89的模式提供long long
,那么它应该也更新其整数文字规则,这样一个不适合long
的文字就有了键入long long
(可能是未签名的)。
但是,我听说编译器存在不执行此操作;除非你把后缀放在自己身上,否则它们会截断文字,而不是给它一个适合的类型。
tl; dr - 后缀不应该是必需的;但是使用它永远不会伤害它,它可以解决严重实现的编译器扩展。