【问题标题】:printf not printing the correct valuesprintf 没有打印正确的值
【发布时间】:2011-09-07 06:42:56
【问题描述】:

我写了一小段 C 代码。

#include<stdio.h>
int main()
{
    int a  = 0;
    printf("Hello  World %llu is here %d\n",a, 1);
    return 0;
}

它正在打印以下输出

Hello World 4294967296 在这里 -1216225312

编译时出现以下警告

prog.cpp:在函数“int main()”中:

prog.cpp:5:警告:格式“%llu”需要类型“long long unsigned int”,但参数 2 的类型为“int”

我知道我需要将 int 转换为 long long unsigned int,但我不明白为什么后来的值会损坏。

提前致谢

【问题讨论】:

标签: c++ c printf


【解决方案1】:

%llu 需要一个 64 位整数。但是你只给了它一个 32 位的整数。

效果是 printf 正在读取的内容相对于您通过的内容“移动”了 32 位。因此,您的“1”没有在正确的位置被读取。

编辑:

现在解释一下输出:

a1 被分开存储 32 位,因为它们都是 32 位整数。 但是,printf 期望第一个参数是 64 位整数。因此它读作a + 2^32 * 1,在你的情况下是4294967296。打印的第二个值未定义,因为它超过了1

【讨论】:

  • @Mystical 你能解释一下你是怎么得到 (a + 2^32 * 1) 的吗?谢谢
  • 这与系统的内存布局有关。一个 32 位整数存储为 4 个连续字节。同样,一个 64 位整数存储为 8 个连续字节。 'A' 和 '1' 都是 32 位整数,在调​​用 'printf()' 时连续存储在内存中,但 'printf()' 会将其读取为 64 位整数。所以它会将它们一起读取为 8 个字节,其中包含一个 64 位整数,其中“a”是低 32 位,“1”是高 32 位。因此 a + 2^32 * 1。这可能听起来很令人困惑 - 也许有人可以解释得更好。
  • @Mystical:我觉得解释很好,我会注意到这在很大程度上取决于系统的字节序(如果字节序被转移,相同的内存将被处理为2^32+a)和方式编译器决定在main 中布局局部变量,这不是标准规定的(它可能决定以相反的顺序存储它们)。因此,虽然解释可以很好地理解行为,但它不能安全地用于预测任何平台或任何其他编译器或编译器标志上的行为。
  • @David:是的,我很清楚字节序依赖,但我尽量不让它变得比现在更混乱。 (stackoverflow.com/questions/7266332/…) 在 big-endian 上,它可能是 1 + 2^32 * a。
  • @Mystical 感谢您的解释。是否总是将 & 1 存储在连续字节中?如果我有另一个变量说 b 而不是 1 会发生什么。
【解决方案2】:

因为代码会导致未定义行为
未定义的行为本质上意味着所有的赌注都没有。

printf 不是类型安全的。在打印出类型时,您必须小心告知printf 正确的格式描述符。

【讨论】:

  • 作为进一步的评论,这适用于所有“可变参数”函数。除非明确告知,否则他们无法分辨传入的类型,例如printf中的格式字符串@
  • +1。这是正确的答案,因为程序的行为是不确定的。
【解决方案3】:

您传递给printf() 的格式导致它期望堆栈上有12 个字节,但您只压入了8 个字节。因此,它会读取您未推送的 4 个字节,并为您提供意外的输出。

确保您通过了 printf() 的预期,并注意编译器的警告。

【讨论】:

    【解决方案4】:

    Long long 是 64 位长,因此会发生这种情况:
    1. printf 抓取 64 位并将其打印为第一个参数
    2.然后在64位的偏移处抓取32位,并打印出来

    由于您将 32 位值传递给第一个参数,因此这两个值都是垃圾

    【讨论】:

      【解决方案5】:

      根据给定的格式,printf 读取 64 位长度的内存区域,其中包含 a 和 1,打印 4294967296。然后它从接下来的 32 位中读取一些垃圾并打印 -1216225312。

      【讨论】:

        猜你喜欢
        • 2020-02-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-07
        • 1970-01-01
        • 2020-11-09
        • 2020-02-10
        • 2021-12-15
        • 2019-11-29
        相关资源
        最近更新 更多