printf-小代码,大问题

简介:

各位C、C++开发的朋友们,有没有想过小小的printf也会有陷阱呢?这篇文章,我们就深入来探究一下(代码均在suse10 32位系统下编译测试通过)。

废话不多说,直接上代码:

1
2
int64_t a = 1;
printf("%d\n", a);

结果是多少呢?当然是1,你可能会说。
我们来看一下结果:

1

果然是1!但是你会不会以为是 a 首先被自动转化成了 int 类型,然后输入为 1的呢?
如果真这么简单,本文到此也该结束了。我们换一个写法:

1
2
3
int64_t a = 1;
int b = 2;
printf("%d, %d\n", a, b);

这次的结果是多少呢?1 和 2?真的吗?我们来看一下结果:

1, 0

好吧,你可能该惊讶了。然而这个结果的确是对的。
如果你还是觉得不可相信,我们再来看一个代码:

1
2
uint32_t uin = 1;
printf("%llu\n", uin);

输入结果是:

13827625253599182849

这是个随机值。也许你会说,不对呀,应该是 1 呀?

这就涉及到 printf 的设计了,printf的第一个参数永远是字符串,他会解析每一个类似 %d 的结构,然后对指针做对应长度的偏移,如%d是4,%lld就是8。(为什么要偏移,请参看这里 从printf谈可变参数函数的实现
所以,当执行如下代码

1
2
3
int64_t a = 1;
int b = 2;
printf("%d, %d\n", a, b);

实际上两个%d分别取得是 a 的低4字节和高4字节,从而分别是1和0(这里还涉及到大小端的问题,本机是小端存储)。
而对于

1
2
uint32_t uin = 1;
printf("%llu\n", uin);

也是一样的道理,先取到的uin作为低4字节,而高4字节则完全随机,从而得到了一个很大的随机数。
知道了这个原因,我们可以做一个测试:

1
2
3
4
5
6
7
8
uint32_t uin = 1;
uint32_t uin2 = 2;
printf("%llu\n", uin, uin2);
 
uint64_t uin3 = uin2;
uin3 = uin3 << 32;
uin3 += uin;
printf("%llu\n", uin3);

uin2比uin先入栈,所以uin2会在高位,uin会在低位。
如果按照我们所解释的,那两个结果应该完全一致,对不对?我们来看一下输出:

8589934593                                                                                                                                                  
8589934593

的确是一样的~

看完这篇文章,当再看到类型不匹配的printf时,心里是不是会感觉更恐怖?哈哈

原创文章,版权所有。转载请注明:转载自Vimer的程序世界 [ http://www.vimer.cn ]


==============================================================================
本文转自被遗忘的博客园博客,原文链接:http://www.cnblogs.com/rollenholt/articles/2196492.html,如需转载请自行联系原作者
相关文章
|
5月前
13.C语言:用printf函数输出数据
13.C语言:用printf函数输出数据
72 0
|
5月前
|
C语言
14.C语言:用scanf函数输出数据
14.C语言:用scanf函数输出数据
92 0
|
5月前
|
C语言
C语言进阶21收尾(编程练习)(atoi,strncpy,strncat,offsetof模拟实现+找单身狗+宏交换二进制奇偶位)(下)
C语言进阶21收尾(编程练习)(atoi,strncpy,strncat,offsetof模拟实现+找单身狗+宏交换二进制奇偶位)
36 0
|
5月前
|
C语言
C语言进阶21收尾(编程练习)(atoi,strncpy,strncat,offsetof模拟实现+找单身狗+宏交换二进制奇偶位)(上)
C语言进阶21收尾(编程练习)(atoi,strncpy,strncat,offsetof模拟实现+找单身狗+宏交换二进制奇偶位)
105 0
|
5月前
|
C语言
深入理解C语言中的printf函数及数据输出
深入理解C语言中的printf函数及数据输出
221 0
|
12月前
|
编译器 C语言 C++
如何解决VS中scanf使用时报错或无法使用的问题
如何解决VS中scanf使用时报错或无法使用的问题
165 0
|
5月前
|
C语言
C语言中printf函数输出数据
C语言中printf函数输出数据
41 0
|
5月前
|
存储 C语言
C语言用printf函数输出数据
C语言用printf函数输出数据
35 0
|
编译器 文件存储 C++
一劳永逸的方法解决函数scanf报错问题
一劳永逸的方法解决函数scanf报错问题
145 0
|
5月前
|
C语言
C语言第三十九弹--判断闰年and打印1000-2000之间闰年
C语言第三十九弹--判断闰年and打印1000-2000之间闰年