-2

从控制台读取后,我试图打印一个特别大的值。当我尝试从两种不同的方式打印它时,一种是在分配后直接打印,一种是使用strtol函数的返回值,我得到不同的输出!有人可以解释一下为什么我注意到两个不同的输出吗?

输入值为:4294967290

这是代码片段。

long int test2 = strtol(argv[1], &string, 10);
printf("the strtol value is %ld\n", test2);
printf("the strtol function value is %ld\n", strtol(argv[1], &string, 10));

输出

the strtol value is -6
the strtol function value is 4294967290
4

1 回答 1

2

你需要做两件事:

  1. #include <stdlib.h>在程序的开头添加该行。这将导致strtol被宣布。(您还需要#include <stdio.h>为了声明printf。)

  2. 添加-Wall到您的编译器标志(如果您使用 gcc 或 clang)。这将导致编译器告诉您需要声明strtol,它甚至可能会建议包含哪个标头。

发生的事情是您没有声明strtol,结果编译器假定它返回一个int.

由于 4294967290 是 2 32 -6,它是 -6 的 32 位二进制补码表示。因为编译器假定strtol返回一个int,所以它生成的代码只查看低位 32 位。由于您将值分配给 a long,因此编译器需要发出对 . 进行符号扩展的代码int。换句话说,它采用低 32 位,就好像它们是有符号整数(将是 -6),然后将 -6 扩大到 a long

在对 的第二次调用中printf, 的返回值strtol被插入到printf参数列表中而不进行转换。你告诉printf参数是 a long(通过使用l标志 in %ld),幸运的是整个 64 位都在参数列表中,因此printf将它们作为 a 读出long并打印“正确”值。

不用说,所有这些都是未定义的行为,您看到的实际输出无法保证;它恰好与您的架构上的编译器一起工作。在其他编译器或其他架构上,情况可能完全不同,包括 和 的位intlong。所以上面的解释虽然可能很有趣,但没有实用价值。如果您简单地包含正确的标头并因此告诉编译器的实际返回类型strtol,您将获得您期望的输出。

于 2015-09-13T04:18:01.600 回答