请注意+星官方帐户,不要错过令人兴奋的内容。
安排更强大的黄微信官方账号|嵌入式列程序员知道他们也使用printf函数,但是您知道它也有“安全风险”吗?让我给您一个示例,如下所示:嵌入式列1问题说明打印的输出数据不是理论值,如下图(右图)所示:嵌入式列2有关问题的进一步说明,请注意以下代码,这类似于以下奇怪现象:int a = 5; floatx = a; //这里的转换没有问题。
%f print x为5.000000printf(“%d ",a); printf("%f &配额); //为什么输出0.000000?-----问题1printf(“%f ",x); printf(" d ",x); //为什么输出为0?-----问题2printf(“%f,%f ",a,x); //输出全部为0.000000为什么? ----问题3printf(“%f,%f ",x,a); //颠倒a和x的顺序。
正常,为什么? ----问题4printf(“%d,%f ",a,x); getchar(); return0;这是四个问题,将在下面回答。
嵌入式专栏3解释了printf()函数的原理以阐明这些问题。
首先,必须阐明printf()函数的工作原理。
printf()维护需要打印的变量堆栈。
默认情况下,参数在堆栈上的顺序是从右到左。
因此,参数在堆栈上之后的存储模型如下图所示:打印时,printf根据字符转换说明符指定的格式从低位地址提取数据。
直到打印该参数。
例如,当遇到%f指定符时,它将提取8个字节的数据,而遇到%d时,它将提取4个字节的数据。
printf()实际上,它不知道参数的数量,它只会根据格式中打印格式的数量来打印堆栈中参数格式后面的地址内容。
这样,printf()实际上就有安全隐患:它将以常规数据输出的形式强行读取内存中的数据,而没有边界检测(很可能发生堆溢出)。
例如,这种代码:char string [] =“ Hello World!”; printf(“ String:%s,再次强行读取一次:%#p &quot ;, string); printf(" String:%s,强制再次读取:%#s &quot ;,字符串);输出如下:字符串:Hello World !,强制再次读取:0X001C1073字符串:Hello World !,强制再次读取:閮嵌入式列4问题说明问题1:printf(“%f ",a)为什么输出0.000000?答:%f提取8个字节。
A只有4个字节,提取的数字占据了float表示的指数部分。
尾数部分为0。
因此最终为0问题2:printf(“%d ",x)为什么输出为0?答案:%d提取4个字节,x有8个字节。
提取的数字实际上是浮点表示法的指数部分(它恰好是0),所以最终是0。
问题3:printf(“%f,%f ",a,x);输出均为0.000000。
为什么?答案:请参阅问题1的说明。
提取八个字节后,以下内容已被弄乱了。
问题4:printf(“%f,%f ",x,a);更改a,x的顺序,这很正常,为什么?答:这是正常情况。
免责声明:本文中的材料来源来自网络,版权归原始作者所有。
如果涉及作品的版权问题,请与我联系以删除。
------------结束------------后台回复“嵌入式C语言”阅读更多相关文章。
跟随微信公众号“嵌入式列”,底部菜单可查看更多内容,并回复“添加群组”。
按照规定加入技术交流小组。
点击“阅读原件”要查看更多共享,欢迎共享,添加书签,点赞和观看。
免责声明:本文内容经21ic授权后发布,版权归原作者所有。
该平台仅提供信息存储服务。
本文仅代表作者的个人观点,不代表该平台的立场。
如有任何疑问,请与我们联系,谢谢!