c - 带有 lld、ld 和 d 类型标识符的 size_t 变量的 printf

标签 c printf

我写了这个小代码:

#include <stdio.h>
int main() {
    size_t temp;
    temp = 100;

    printf("lld=%lld, ld=%ld, u=%u\n", temp, temp, temp);

    return 0;
}

我在装有 gcc 4.1.1 20070105 (Red Hat 4.1.1-52)i386 GNU/Linux 机器上运行。这是我得到的输出:

lld=429496729700, ld=100, u=7993461

我可以理解第一个 (lld) 被打印为垃圾,因为 printf 试图打印 8 个字节(对于 signed long longlld 所示)当变量 temp 中只有 4 个字节可用时。 但是,我不明白为什么最后一个标识符 u 被打印为垃圾 - 而据我所知,这是最接近 size_t 的适用标识符。

这里我假设 size_tunsigned int(对于我的 i386,它是有符号的 4 字节)。

现在,我对 printf 行做了一些调整:

...
printf("ld=%ld, u=%u, lld=%lld\n", temp, temp, temp);
...

我有一个完美的答案(lld 部分除外)。

ld=100, u=100, lld=34331653576851556

有人可以帮我理解我到底错过了什么吗?

非常感谢您的帮助!

[旁注:我尝试使用 gcc -O[0,2] 标签打开/关闭优化,观察结果没有任何差异。]

最佳答案

那是因为您压入堆栈的是三个 32 位值,而您的格式字符串试图使用其中的四个,或者更准确地说,一个 64 位值和两个 32 位值。

在第一种情况下,lld 获取两个 32 位值,ld 获取第三个值,u 获取之后发生在堆栈中的任何东西,实际上可以是任何东西。

当您更改字符串中格式说明符的顺序时,它的工作方式不同,因为 ld 吸收了第一个 32 位值,u 吸收了second 和 lld 吸取第三个 plus 之后堆栈中的任何内容。这就是您获得不同值的原因,这是一个数据对齐/可用性问题。

您可以看到第一个值的实际效果。 429496729700 等于 (4294967296 + 1) * 100,即 (232+1)*100。你的代码片段

printf("lld=%lld, ld=%ld, u=%u\n", temp, temp, temp);

实际有以下作用:

What you pass     Stack     What printf() uses
-------------     -----     ------------------
                 +-----+
100              | 100 | \
                 +-----+  = 64-bit value for %lld.
100              | 100 | /
                 +-----+
100              | 100 |    32-bit value for %ld.
                 +-----+
                 | ?   |    32-bit value for %u (could be anything).
                 +-----+

第二种情况

printf("ld=%ld, u=%u, lld=%lld\n", temp, temp, temp);

发生以下情况:

What you pass     Stack     What printf() uses
-------------     -----     ------------------
                 +-----+
100              | 100 |    32-bit value for %ld.
                 +-----+
100              | 100 |    32-bit value for %u.
                 +-----+
100              | 100 | \
                 +-----+  = 64-bit value for %lld (could be anything).
                 | ?   | /
                 +-----+

关于c - 带有 lld、ld 和 d 类型标识符的 size_t 变量的 printf,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2424528/

相关文章:

c - 用多个引号引起来的字符串初始化 C 字符串

c - 如何读取数组中int的随机数

c - 为什么使用 -Os 编译会使这个函数变大?

c++ - %n 格式说明符程序在不同的编译器上给出不同的输出。为什么?

objective-c - C printf 格式说明符 %_fi

C:评估字符串的一部分

c - 哪些项目(结构)知道它们在数组中的位置的静态数组

c - printf 如何在 CUDA 计算上工作 >= 2

c - fprintf() 和 fputs() 没有得到正确的结果

c - 为什么 printf 有助于防止以下代码中的段错误?