【问题标题】:Inconsistent results from printf with long long int?printf 与 long long int 的结果不一致?
【发布时间】:2009-11-17 13:26:08
【问题描述】:
struct DummyStruct{
        unsigned long long std;
        int type;
};

DummyStruct d;
d.std = 100;
d.type = 10;

/// buggy printf, unsigned long long to int conversion is buggy.
printf("%d,%d\n",d.std, d.type);  // OUTPUT: 0,100 
printf("%d,%d\n", d.type, d.std); // OUTPUT: 10,100 
printf("%lld,%d\n",d.std, d.type); // OUTPUT: 100,10

请告诉我为什么在 printf 中没有正确处理 unsigned long long 到 int 的转换。我正在使用 glibc。

这是 printf 中的错误吗?

为什么 printf 不做内部类型转换?

【问题讨论】:

  • 谢谢 Mykola,现在我已经纠正了我的错误。
  • 大多数编译器都会对您犯的错误发出警告 - 您是否忽略了它?或者你没有打开警告?他们在那里是有原因的。

标签: c++ c printf


【解决方案1】:

%d 参数告诉printf 将相应的参数解释int。尝试将%llu 用于long long。并记住这个reference card

(所以不,这不是错误)

【讨论】:

  • (这是一个错误,但不是printf,而是上面的程序:-))
  • @pixelbeat:我每天都很享受。
【解决方案2】:

这是您的使用问题。 除非格式字符串中指定的类型与参数中的类型完全相同,否则事情将无法正常工作。

这是因为编译器将参数按原样压入堆栈。
没有类型检查或转换。

在运行时,代码会拉取堆栈的值并根据格式字符串中的值前进到下一个对象。如果格式字符串错误,则表示金额不正确,您会得到有趣的结果。

【讨论】:

    【解决方案3】:

    规则一:在库或编译器中发现错误的可能性非常非常小。始终假设编译器/库是正确的。

    参数通过<stdarg.h>(变量参数列表)中的机制传递给printf(),这涉及到堆栈上的一些魔法。

    没有过多的细节,printf() 所做的是假设它必须从堆栈中提取的下一个参数是格式字符串中指定的类型 - 在 @ 的情况下987654324@,一个有符号整数

    如果您放入其中的实际值的宽度小于或等于int,则此方法有效,因为在内部,堆栈上传递的任何较小值都会扩展到@987654326 的宽度@通过一种称为“整数提升”的机制。

    但是,如果您传递给printf() 的类型比int,这将失败:printf() 被告知(由您的%d)期待int ,并从堆栈中提取适当数量的字节(假设 32 位 int 为 4 个字节)。

    如果您的long long(我们假设 64 位值是 8 个字节),这将导致 printf() 仅获得您的 long long一半。其余的仍在堆栈中,如果您在格式字符串中添加另一个 %d,将会产生非常奇怪的结果。

    ;-)

    【讨论】:

      【解决方案4】:

      使用 printf(这是原始 C 中非常古老的函数之一),编译器不会将格式列表后面的参数转换为所需的类型,即您需要确保自己的参数列表中的类型与一种格式。

      对于大多数其他函数,编译器将给定参数压缩到声明的类型中,但 printf、scanf 和朋友需要 准确地告诉编译器后面是哪些类型。

      【讨论】:

      • 这是printfscanf 和类似的没有声明这些参数的类型的直接结果——它们不能,因为这就是变量参数的全部意义——列出函数。
      猜你喜欢
      • 1970-01-01
      • 2011-05-08
      • 1970-01-01
      • 2020-09-03
      • 1970-01-01
      • 2012-11-15
      • 2010-09-05
      • 1970-01-01
      相关资源
      最近更新 更多