C语言printf4个字节,C语言printf()函数详解和安全隐患

一、问题描述

6c2d867f653266647a2fa6f6f8d632d8.png

二、进一步说明

请仔细注意看,有如下奇怪的现象

int a=5;

floatx=a; //这里转换是没有问题的,%f打印x是 5.000000

printf("%d\n",a);

printf("%f\n",a); //输出为什么是0.000000? -----问题1

printf("%f\n",x);

printf("%d\n",x); //输出为什么是0? -----问题2

printf("%f,%f\n",a,x); //输出都是0.000000 为什么? ----问题3

printf("%f,%f\n",x,a); //调换一下a,x的顺序,正常了,为什么? ----问题4

printf("%d,%f\n",a,x);

getchar();

return0;

三、printf()函数的原理解释

明白这些问题首先需要明白printf()函数的工作原理。

printf()维持了一个需要打印的变量栈,默认情况下,参数进栈的顺序是由右向左的,因此,参数进栈以后的内存模型如下图所示:

d06df15a1e43ac170703f06d8f36bc75.png

打印的时候,printf按照字符转换说明符规定的格式从低地址开始提取数据,直到参数打印完。

比如遇到 %f 说明符就提取8个字节的数据,遇到 %d 就提取4个字节。看到这里,你也许会问一个问题,如果后面的字节数不够了怎么办?

恭喜你,你发现了printf()的安全隐患,没错,它会强行读取临近内存的数据当作正常数据输出————很有可能产生堆溢出!

比如这样的代码:

char string[]="Hello World!";

printf("String: %s ,强行再读一次: %#p , 再读一次: %#p\n", string);

输出如下:

String:Hello World! , 强行再读一次: 0X001C1073 , 再读一次: 0X001C1073

三、问题解释

(1)问题1:printf("%f\n",a) 输出为什么是0.000000?

答:%f 提取8字节,a只有4字节,提取出来的数占了float表示法的指数部分,尾数部分为0,所以最终是0

(2)问题2:printf("%d\n",x)  输出为什么是0?

答:%d 提取4字节,x有8字节,提取出来的数实际上是float表示法的指数部分(恰好是0),所以最终是0

(3)问题3:printf("%f,%f\n",a,x); 输出都是0.000000 为什么?

答:参照问题1的解释,提取了八字节后,后面的已经乱了

(4)问题4:printf("%f,%f\n",x,a);调换一下a,x的顺序,正常了,为什么?

答:这是正常的情况而已。

版权声明:本文为博主原创文章,未经博主允许不得转载。

原文:http://blog.csdn.net/a369414641/article/details/47447193

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值