LONG_MAX-1是64位机器吗?
我发现 LONG_MAX (9223372036854775807) 实际上保存在 64 位机器的 long 类型变量上,如下所示。
Hex: 0xffff ffff ffff ffff ffff ffff ffff ffff
Bin: 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111
据我所知,最高有效位用作有符号位。
Windows 计算器中的 9223372036854775807 更改如下。
Hex: 0x7fff ffff ffff ffff ffff ffff ffff ffff
Bin: 01111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111
Hex: 0x7fff ffff ffff ffff ffff ffff ffff ffff
Bin: 01111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111
所以,恕我直言,LONG_MAX 应该保存如下
long 变量是否被视为无符号值?
我注意到有人问我是如何发现这种情况的。
我在下面的代码中发现了这种情况。
#include <stdio.h>
#include <limits.h>
int main(int argc, char *argv[])
{
long a;
a = strtol(argv[1], NULL, 0);
printf("%ldn", a);
return 0;
}
实际上,我没有使用 LONG_MAX 宏,但是当我执行程序时,我静态使用了 9223372036854775807 值。
我检查了该值作为 0x7fff 是安全的 ... 使用 gdb 如下所示
Reading symbols from test...done.
(gdb) b main
Breakpoint 1 at 0x40055c: file test.c, line 8.
(gdb) r 9223372036854775807
Starting program: ./test 9223372036854775807
Breakpoint 1, main (argc=2, argv=0x7fffffffe308) at test.c:8
8 a = strtol(argv[1], NULL, 0);
(gdb) n
10 printf("%ldn", a);
(gdb) x/gt &a
0x7fffffffe218: 1111111111111111111111111111111111111111111111111111111111111111
(gdb)
即使我没有使用 LONG_MAX 宏,值 9223372036854775807 也与 LONG_MAX 宏相同。
所以,我认为它应该保存为 0x7fff ......就像使用 LONG_MAX。
回答
您忘记包含<stdlib.h>,因此您的编译器发出警告,例如warning: implicit declaration of function ‘strtol’.
当您选择忽略警告时,编译器只是将返回值strtol视为int(32 位值)而不是long(64 位值),因此会发生从 64 位到 32 位的截断,因此存在差异。
示范:
#include <stdio.h>
#include <limits.h>
//#include <stdlib.h>
int main(int argc, char *argv[])
{
long a, b;
a = strtol("9223372036854775807", NULL, 0);
b = LONG_MAX;
printf("%ld %ldn", a, b);
}
运行它并没有取消注释#include <stdlib.h>。
结论:始终将包含“隐式”一词的警告视为错误。
- @JoontaekOh gcc 4.8.5 is very old and this warning is not enabled by default. Compile with the `-Wall` option or even better install a more recent version of gcc. The current version is 10.2 (I think)