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,但没有给出任何警告.
为什么我不能在没有警告声明它被隐式转换的情况下这样做 - 当我明确地声明它时?
您显式声明了它,但没有 U,这将使其成为无符号的。由于该值没有带符号的整数常量,因此它隐式地使其成为无符号的,从而为您提供最好将其显式显示的信息。
这样做与a = 18446744073709551615U;.
每C标准,十进制常量的没有后缀的类型是int,long int,或long long int,特别是那些第一即足以表示价值的.在您的C实现中,这些都不能代表18446744073709551615,因为它太大了.
为了适应您,编译器正在创建它的类型unsigned long.从技术上讲,这不符合C标准,因此编译器会警告您.
在这种情况下,不会造成任何伤害,因为您要将值分配给unsigned long.但是在某些情况下使用错误的类型会导致问题,因此通常应该为这些常量添加后缀,以确保它们与预期的使用方式相匹配.在这种情况下,a u就足够了; 如无后缀的类型,编译器会决定是否使用unsigned int,unsigned long int或unsigned long long int取决于数的大小和类型的能力.