C 警告:整数常量对于“long”类型太大

C 警告:整数常量对于“long”类型太大,c,gcc,gcc-warning,C,Gcc,Gcc Warning,我有以下代码 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位的无符号整数

我有以下代码

  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位的无符号整数

为什么编译器会生成此警告?

常量0xFFFF000000对于32位的长度来说太大,在您的示例中,范围为0x7fffffff

将其写入0xFFFF000000ULL无符号长 或者通过写作来避免这个问题

reg_val = (val >> 24) & 0xFFFFFF;

对greggo的好答案进行一点扩展

整数文本的定义方式取决于我们使用的语言版本

在C99中,除非不存在整型文字,否则整型文字会自动具有一个可以包含其值的类型。因此,假设长度为32位,那么这个常量的类型已经是unsigned long long,所以不应该出现警告

我没有C89文本的副本,但C89没有长文本。如果规则相似,那么将发生的情况是,该常量以实现定义的方式转换为32位无符号长,可能会截断更高的位

由于OP得到了一个警告,但也能够用ull后缀解决它,这表明他正在使用编译器扩展。理论上,如果编译器在类似C89的模式下提供long-long,那么它还应该更新其整数文本规则,以便不能放入long的文本具有可能无符号的long-long类型

然而,我听说存在不这样做的编译器;除非你自己加上后缀,否则他们会截断文本而不是给它一个合适的类型


tl;dr后缀不应该是必需的;但是使用它不会有什么坏处,而且它可以解决实现不好的编译器扩展。

在右移值以删除低24位之前屏蔽低24位的目的是什么?在我看来,它似乎是多余的代码,没有真正的用途。我想,它避免了高位中的任何内容。我隐约记得,为了让编译器满意,您需要将LL附加到文本中。@greggo-这不是只有在我们进行右转而不是右移时才有用吗?也就是说,在LSB作为MSB插入而不是丢弃的情况下,就像右移/左移的情况一样。@enhzflep,它也可以是val&0xfffffffffull>>24,或者val>>24&0xFFFFFF,但是当使用第一种形式时,通常会在移位丢弃的位中为掩码使用零,只是为了弄清楚哪些部分会保留下来。我所说的“高位”是指不能简化为val>>24,因为它保留了uint64的位55:24,而不是所需的47:24-因此屏蔽操作本身不是冗余的,只是它的一些效果。。。我可能误解了你的问题。或者他们会升级到适合的类型,但会对此发出警告,这是一个很好的警告,以防你将代码转移到其他编译器中。整个“自动类型”方法的一个问题是:如果您有例如0xFFFF0000,根据它是按uint32还是按int64执行,它可能会对结果产生很大的影响。假设我的表达式是intvar1+Literal_Const*intvar2>>8,Literal_Const是0x7FFF8000、0xFFFF0000或0x1FF0000;因此取int32、uint32或int64。那是一条相当崎岖的路。在这种情况下,显式类型是必不可少的。0xFFFF0000必须根据C99进行无符号签名,而且我认为对于C89,除了这两个版本之间的long-long之外,AFAIK规则对于其他类型没有更改-较小的宽度类型始终优先于较大的宽度类型,毛发十六进制和八进制常量,但对于十进制常量则没有!在这个例子中,一个明智的选择是将intvar1设为ull,这将导致另一个被提升为任何类型;由于十六进制文字总是正值,所以符号扩展或任何东西都没有问题。当然,不是说你不应该在上面加后缀。我指的是“崎岖不平的道路”,我可能希望>>是用符号扩展来完成的,如果Literal_Const被视为无符号,这是不会发生的。。。但是如果它被作为一个int,它将被接受。因此,一个可能意外的依赖于一个常量的值。制作intvar1 ull确实可以确保一致地处理它。由于遇到了一些这样的问题,我倾向于使用比以前更多的明显冗余的类型转换。