为什么GCC在将无符号长度设置为2 ^ 64-1时会发出警告?

Tim*_*Tim 3 c gcc

C标准规定a long int至少为4个字节 - 在我的系统上它是8个字节.

这意味着我可以在a中存储最多2 ^ 63 -1的值,在a中存储long2 64 -1 unsigned long.

但是,当使用该-Wall标志编译以下代码时,它会发出警告[Wimplicitly-unsigned-literal]:

int main (int argc, char ** argv) {

  unsigned long a;
  a = 18446744073709551615; // 2^64-1

}
Run Code Online (Sandbox Code Playgroud)

如果我使用2 63 -1(9223372036854775807)代替它,它编译没有警告(正如预期的那样 - 2 63 -1将适合a signed long int).

对于一个项目,我需要具有最大值unsigned long,并且我发现(9223372036854775807 << 1) + 1不会引发此警告.然后我的老师建议我可以使用已ULONG_MAX定义的内容limits.h,但没有给出任何警告.

为什么我不能在没有警告声明它被隐式转换的情况下这样做 - 当我明确地声明它时?

glg*_*lgl 5

您显式声明了它,但没有 U,这将使其成为无符号的。由于该值没有带符号的整数常量,因此它隐式地使其成为无符号的,从而为您提供最好将其显式显示的信息。

这样做与a = 18446744073709551615U;.

  • @NikosC.:在这种情况下不需要“ul”或“ull”。C 标准规定十进制常量的类型会进行一定程度的调整以适应该值。如果使用“u”后缀,则类型将是第一个可以表示该值的“unsigned int”、“unsigned long int”或“unsigned long long int”。 (2认同)

Eri*_*hil 5

每C标准,十进制常量的没有后缀的类型是int,long int,或long long int,特别是那些第一即足以表示价值的.在您的C实现中,这些都不能代表18446744073709551615,因为它太大了.

为了适应您,编译器正在创建它的类型unsigned long.从技术上讲,这不符合C标准,因此编译器会警告您.

在这种情况下,不会造成任何伤害,因为您要将值分配给unsigned long.但是在某些情况下使用错误的类型会导致问题,因此通常应该为这些常量添加后缀,以确保它们与预期的使用方式相匹配.在这种情况下,a u就足够了; 如无后缀的类型,编译器会决定是否使用unsigned int,unsigned long intunsigned long long int取决于数的大小和类型的能力.