摩登3娱乐怎么样?_C语言printf()函数具体解释和安全隐患

关注+星标公众,不错过精彩内容

编排 | strongerHuang

微信公众号 | 嵌入式专栏



程序员都知道,也都会使用printf函数,但你知道它也有“安全隐患”吗?


下面就来举例我说说:


嵌入式专栏

1

问题描述

打印输出的数据并不是理论值,如下图(右边):

嵌入式专栏

2

进一步描述问题

请细致注意看下面代码,有如以下奇怪的现象:

int a=5;floatx=a; //这里转换是没有问题的。%f打印x5.000000
printf("%d\n",a);printf("%f\n",a); //输出为什么是0.000000?-----问题1printf("%f\n",x);printf("%d\n",x); //输出为什么是0?-----问题2printf("%f,%f\n",a,x); //输出都是0.000000 为什么? ----问题3printf("%f,%f\n",x,a); //调换一下a,x的顺序,正常了,为什么?----问题4printf("%d,%f\n",a,x);
getchar();return0;


这里有四个问题,下面会进行解答。




嵌入式专栏

3

printf()函数的原理解释
明确这些问题首先须要明确printf()函数的工作原理。


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



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


比方遇到 %f 说明符就提取8个字节的数据,遇到 %d 就提取4个字节。printf()事实上不知道参数的个数,它仅仅会依据format中的打印格式的数目依次打印堆栈中参数format后面地址的内容。


这样一来,printf()事实上存在安全隐患:它会强行读取内存的数据当作正常数据输出,没有边界检测(非常有可能产生堆溢出


比如这种代码:
char string[]="Hello World!";printf("String: %s ,强行再读一次: %#p\n", string);printf("String: %s ,强行再读一次: %#s\n", string);


输出如下:
String:Hello World! , 强行再读一次: 0X001C1073 String: Hello World! ,强行再读一次: 閮


嵌入式专栏

4

问题解释

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

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


问题2:printf(“%d\n”,x)  输出为什么是0?
答:
%d 提取4字节,x有8字节。提取出来的数实际上是float表示法的指数部分(恰好是0),所以终于是0


问题3:printf(“%f,%f\n”,a,x); 输出都是0.000000 为什么?
答:
参照问题1的解释。提取了八字节后,后面的已经乱了


问题4:printf(“%f,%f\n”,x,a);调换一下a,x的顺序,正常了,为什么?
答:
这是正常的情况而已。


免责声明:本文素材来源网络,版权归原作者所有。如涉及作品版权问题,请与我联系删除。


————  



免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!