使用printf

时间:2015-09-13 02:38:11

标签: c strtol

我正在尝试从控制台读取后打印特别大的值。当我尝试从两种不同的方式打印它时,一种是在分配之后,一种是来自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

1 个答案:

答案 0 :(得分:2)

你需要做两件事:

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

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

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

    由于4294967290是2 32 -6,因此它是-6位的32位Two's-complement表示。因为编译器假定strtol返回int,所以它生成的代码只查看低位32位。由于您要将值赋给long,因此编译器需要发出对int进行符号扩展的代码。换句话说,它需要低位32位,就像它们是有符号整数(它将是-6)然后将-6加宽到long

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

    毋庸置疑,所有这些都是未定义的行为,您所看到的实际输出无法保证;它恰好与您的架构上的编译器一起工作。在其他一些编译器或其他架构上,事情可能完全不同,包括longint的位长。因此,上述解释尽管可能有趣,但没有实际价值。如果您只是包含正确的标题,从而告诉编译器long的实际返回类型,您将获得预期的输出。