大概 2013 年前后看 C Primer Plus 的时候,出于对 printf 函数原理的理解,写下了下面的代码(ago 变成了 verybig)
#include <stdio.h>
int main(void)
{
long long verybig = 12345678908642;
printf("%ld %ld", verybig, verybig);
return 0;
}
7 年前的输出:
1942899938 2874
7 年后的今天的输出( gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) ):
$ gcc test2.c -o test -g && ./test
test2.c: In function ‘main’:
test2.c:5:15: warning: format ‘%ld’ expects argument of type ‘long int’, but argument 2 has type ‘long long int’ [-Wformat=]
printf("%ld %ld", verybig, verybig);
~~^
%lld
test2.c:5:19: warning: format ‘%ld’ expects argument of type ‘long int’, but argument 3 has type ‘long long int’ [-Wformat=]
printf("%ld %ld", verybig, verybig);
~~^
%lld
12345678908642 12345678908642%
我已记不清 7 年前用的是什么编译器了,C Primer Plus 书中写的 printf 从右至左压栈却依稀可见~
7 年后的解释可以参见: https://blog.iret.xyz/article.aspx/printf_magic_float
难不成 7 年前 printf 是把所有参数都压栈,7 年后是整型和浮点型存寄存器,其他压栈?
1
BrettD 2021-06-17 15:44:08 +08:00 via iPhone
long 的长度在不同平台上不一定相同,所以 ld 可能能用也可能不对
|
2
ysc3839 2021-06-17 15:54:15 +08:00 via Android 2
long long 要配合 %lld 来用,你那么写大概是 UB,出现任何结果都是符合标准的。
|
4
qwerrewt 2021-06-17 17:04:42 +08:00 1
你说的部分是对的,但关键点不对。这个就是 32 位和 64 位的区别,可能你之前是 32 位机器,现在是 64 位。
验证方法很简单,你加参数-m32 重新编一下,结果应该就和你之前一样了。 |
5
3dwelcome 2021-06-17 17:24:38 +08:00
@hanssx 翻过书了,2 楼说的没错。
书里的例子就不是你首楼写的代码,书里也明确提到:"so use the %ld specifier for long", "the long long types use %lld and %llu" 那么%ld 是 32 位 long,%lld 是 64 位 long long,两个 GCC 运行结果都没错,是你 7 年前写错了。 |
6
hanssx OP @qwerrewt 老哥厉害,果然如你所说,第一次真切感受到 32 位和 64 位的区别
``` $ gcc -m32 test2.c -o test -g && ./test test2.c: In function ‘main’: test2.c:5:15: warning: format ‘%ld’ expects argument of type ‘long int’, but argument 2 has type ‘long long int’ [-Wformat=] printf("%ld %ld", verybig, verybig); ~~^ %lld test2.c:5:19: warning: format ‘%ld’ expects argument of type ‘long int’, but argument 3 has type ‘long long int’ [-Wformat=] printf("%ld %ld", verybig, verybig); ~~^ %lld 1942899938 2874% ``` @3dwelcome 你可以试试在 32 位机器上的结果是不是和我一样 |
7
iceheart 2021-06-17 19:47:14 +08:00 via Android 1
%ld 是写 long 型变量的 , %lld 是写 long long 型变量的。
gcc/clang 64 位模式 long 型长度是 64 位, 32 位模式长度是 32 位; msc 的 32 位 64 位模式 long 型长度都是 32 位。 |
8
Nitroethane 2021-06-17 22:38:23 +08:00 1
printf 函数从右向左压栈是因为 x86 架构下函数调用时是通过栈传参,amd64 架构下函数调用是通过寄存器传参。
|
9
jackleeforce3615 2021-06-25 11:18:09 +08:00
%lu 可以吗
|