C:打印大号

And*_*ech 11 c printf

请考虑以下事项:

#include <stdio.h>

main() {
    unsigned long long verybig = 285212672;

    printf("Without variable : %llu\n", 285212672);
    printf("With variable    : %llu", verybig);
}
Run Code Online (Sandbox Code Playgroud)

这是上述程序的输出:

Without variable : 18035667472744448
With variable    : 285212672
Run Code Online (Sandbox Code Playgroud)

从上面可以看到,当printf将数字作为常量传递时,它会输出一些巨大的错误数字,但是当该值首次存储在变量中时,会printf输出正确的数字.

这背后的原因是什么?

pax*_*blo 25

尝试285212672ULL; 如果你在没有后缀的情况下编写它,你会发现编译器将它视为常规整数.它在变量中工作的原因是因为整数正在转换unsigned long long为赋值中的一个,因此传递给的值printf()是正确的类型.

你问之前,没有,编译器可能足够聪明,从弄明白了"%llu"中的printf()格式字符串.这是一个不同的抽象级别,编译器负责语言的语法,printf()语义是不是部分语法,它是一个运行时库函数(除了它包含在标准中之外,与您自己的函数没有什么不同).

对于32位int和64位unsigned long long系统,请考虑以下代码:

#include <stdio.h>

int main (void) {
    printf ("%llu\n",1,2);
    printf ("%llu\n",1ULL,2);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

哪个输出:

8589934593
1
Run Code Online (Sandbox Code Playgroud)

在第一种情况下,两个32位整数1和2被压入堆栈并将其printf()解释为单个64位ULL值,2 x 2 32 + 1.该2参数无意中包含在ULL值中.

在第二种情况下,您实际上会推送64位1值和多余的32位整数2,这将被忽略.

请注意,格式字符串与实际参数之间的"不合时宜"是一个坏主意.就像是:

printf ("%llu %s %d\n", 0, "hello", 0);
Run Code Online (Sandbox Code Playgroud)

可能会崩溃,因为32位"hello"指针将被消耗%llu,%s并将尝试取消引用最终0参数.下面的"图片"说明了这一点(我们假设单元格是32位,"hello"字符串存储在0xbf000000.

What you pass     Stack frames     What printf() uses
                 +------------+
0                | 0          | \
                 +------------+  > 64-bit value for %llu.
"hello"          | 0xbf000000 | /
                 +------------+
0                | 0          |    value for %s (likely core dump here).
                 +------------+
                 | ?          |    value for %d (could be anything).
                 +------------+
Run Code Online (Sandbox Code Playgroud)


caf*_*caf 5

值得指出的是,有些编译器会针对这种情况提供有用的警告 - 例如,这就是GCC对您的代码所说的内容:

x.c: In function ‘main’:
x.c:6: warning: format ‘%llu’ expects type ‘long long unsigned int’, but argument 2 has type ‘int’
Run Code Online (Sandbox Code Playgroud)

  • 还有一个不忽略编译*警告*的原因。 (2认同)