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

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

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

1

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

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

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

1, 0

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

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

输入结果是:

13827625253599182849

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

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

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字节则完全随机,从而得到了一个很大的随机数。
知道了这个原因,我们可以做一个测试:

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时,心里是不是会感觉更恐怖?哈哈

printf 小函数 大问题-转相关推荐

  1. printf 小代码 大问题

    技术 对于我来说 是我前进的动力 虽然有时候感觉会枯燥乏味 不过没关系 放松一下紧张的心态 做一些你能够是你进步的事情  这样 你才会觉得  每天都过得很充实  学海无涯  坚持追求你所想要实现的梦想 ...

  2. 用shell脚本计算日期的小函数们

    参考:http://qiuqiang1985.iteye.com/blog/1647761 参考:http://my.oschina.net/SmileWolf/blog/159624 当你遇到一个d ...

  3. 如何用单片机写出类似printf的函数

    实现功能:stm32用类似printf的函数,通过串口发送数据. 首先,让我们在qt中用C语言模拟串口输出(用printf("%c",ch)代替void USART_SendDat ...

  4. 函数要多小才够好——谈小函数之道

    源地址:http://kb.cnblogs.com/page/154245/ "设计良好的函数往往比较小,而过大函数的设计往往一塌糊涂,或者存在很大的优化空间." 也许你认为讨论函 ...

  5. JS_ECMA基本语法中的几种封装的小函数-1

    今天给大家介绍js ECMA中几个封装的小函数以及一些常用的函数小案例: 1,找重复的函数 <script>//在数组里面找重复:function findInArr(n,arr){for ...

  6. 邪恶的Java帝国是怎么欺负小函数的?

    1 小函数的运气不好,投胎到了邪恶的Java帝国,一出生就被告知了自己的悲惨地位,以及未来的悲惨人生:奴隶. 确切地说,是类的奴隶. 在Java帝国, 国王特别喜欢"类", 不待见 ...

  7. 我写的一个给time_t赋值的小函数

    我写的一个给time_t赋值的小函数 //======================================== // 功能:将固定格式的时间转化为 time_t 日历时间 //       ...

  8. JS_ECMA基本语法中的几种封装的小函数

    先来回顾一下我们的字符串: 字符串方法: str.length str.charAt(i):取字符串中的某一个; str.indexOf('e');找第一个出现的位置;找不到返回-1; str.las ...

  9. 转:函数要多小才够好——谈小函数之道

    转载自: http://justjavac.com/other/2012/05/29/to-use-little-function.html "设计良好的函数往往比较小,而过大函数的设计往往 ...

最新文章

  1. 使用数字示波器DS6104测量交流信号的幅值和相位
  2. android getChildAt(index)返回null问题解决方法
  3. sift的java实现解述
  4. 周长相等的正方形面积一定相等_万萍:画图研究图形与几何问题—怎样围面积更大(四下)...
  5. Data-structures-and-algorithms-interview-questions-and-their-solutions
  6. node oauth2验证_如何设置和使用护照OAuth Facebook身份验证(第1部分)| Node.js
  7. 发现Tensorflow
  8. java单线程共享,「Java并发编程实战」之对象的共享
  9. 碰到 oracle 10g ORA-00257
  10. linux刷机软件,MTK平台刷机工具——SP_Flash_Tool
  11. 虚拟机网络配置(配置动态ip和静态ip)
  12. 获取Audio音乐的总时长
  13. 王者荣耀英雄分析--孙悟空
  14. HPUACM暑期集训第二次积分训练赛 C——Simplest
  15. 使用开源人脸特征提取器进行脸部颜值评分
  16. 锤子使用手册 android,锤子爱好者的新手使用指南
  17. Android-屏幕截图功能实现
  18. 【调研】消费者调研与市场调研的区别
  19. life is...
  20. 一篇理解GFS与HDFS的重要理念

热门文章

  1. python函数详解_Python函数详解(转)
  2. Android 百度地图开发(三)--- 实现比例尺功能和替换自带的缩放组件
  3. javascript 总结(常用工具类的封装,转)
  4. CrazyWing:Python自动化运维开发实战 五、Python运算符与表达式
  5. springboot 常用插件
  6. java --微信支付2
  7. linux 源码安装 Nginx
  8. 解决ScrollViewer嵌套的DataGrid、ListBox等控件的鼠标滚动事件无效
  9. 6 Linux之bash环境配置
  10. 利用Civil 3D API更改曲面的样式