一、问题描写叙述

二、进一步说明

请细致注意看,有例如以下奇怪的现象

        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()维持了一个须要打印的变量栈。默认情况下,參数进栈的顺序是由右向左的,因此,參数进栈以后的内存模型例如以下图所看到的:

打印的时候,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!  ,强行再读一次: 閮

三、问题解释

(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的顺序,正常了,为什么?

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

C语言printf()函数具体解释和安全隐患的更多相关文章

  1. C语言printf()函数:格式化输出函数

    C语言printf()函数:格式化输出函数 头文件:#include <stdio.h> printf()函数是最常用的格式化输出函数,其原型为:     int printf( char ...

  2. C语言printf函数转换说明表及其修饰符表

    请求printf()函数打印数据的指令要与打印数据的类型匹配. 例如, 打印整数时使用%d, 打印字符是使用%c. 这些符号被称为转换说明, 他们指定了数据转换称可显示的形式. 1. ANSI C标准 ...

  3. C语言scanf函数详细解释

    原文链接 函数名: scanf 功 能: 执行格式化输入 用 法: int scanf(char *format[,argument,...]); scanf()函数是通用终端格式化输入函数,它从标准 ...

  4. C语言scanf函数详细解释(转载)

    原文地址:https://blog.csdn.net/21aspnet/article/details/174326 scanf 函数名: scanf 功 能: 执行格式化输入 用 法: int sc ...

  5. C语言 Printf函数

    #include <stdio.h> int main(int argc, const char * argv[]) { // insert code here... printf(&qu ...

  6. C语言printf函数

    #include<stdio.h> //int float double short char long int main() { //int printf(const char *for ...

  7. 【C语言】printf函数详解

    C语言printf函数详解 一.相关基础知识 请求printf()打印变量的指令取决于变量的类型,例如打印整数用%d符号,打印字符用%c符号,这些符号称为转换说明(conversion specifi ...

  8. MFC 中的 “printf” 函数

    怀念C语言的我,MFC没法使用的C语言printf函数,于是: int MFCprintf(const char* m_data, ...){ CString str; char printf_buf ...

  9. C语言中可变参数的原理——printf()函数

    函数原型: int printf(const char *format[,argument]...) 返 回 值: 成功则返回实际输出的字符数,失败返回-1. 函数说明: 使用过C语言的人所再熟悉不过 ...

随机推荐

  1. js--如何判别 null undefined

    收集资料如下判断: 1.判断undefined: ? 1 2 3 4 var tmp = undefined; if (typeof(tmp) == "undefined"){ a ...

  2. linux救援

    1.单用户模式(类比win的安全模式) 1.1.开机按任意键 1.2.按E进入编辑模式 1.3.光标移动到第二个(“kernel xxxx”)按e 1.4.在quiet 后面输入“ 1” or “S” ...

  3. angular 创建项目

    介绍有很多可用的工具可以帮助你开发AngularJS 应用,那些非常复杂的框架不在我的讨论范围之中,这也是我开始这系列教程的原因.在第一部分,我们掌握了angularjs框架的基本结构,开发了第一应用 ...

  4. PL/SQL配置访问多个不同IP的oracle

     第一步:打开Oracle的tnsnames.ora文件.添加 test = (DESCRIPTION =    (ADDRESS_LIST =      (ADDRESS = (PROTOCOL = ...

  5. 九度oj 题目1130:日志排序

    题目描述: 有一个网络日志,记录了网络中计算任务的执行情况,每个计算任务对应一条如下形式的日志记录:“hs_10000_p”是计算任务的名称,“2007-01-17 19:22:53,315”是计算任 ...

  6. Git升级迁移

    1 原有机器进行升级和备份: https://about.gitlab.com/update/#centos-6 1. Make a backup (Optional) If you would li ...

  7. iOS学习笔记18-CoreData

    一.CoreData介绍 CoreData是iOS5之后新出来的的一个框架, 是对SQLite进行一层封装升级后的一种数据持久化方式.它提供了对象<-->关系映射的功能,即能够将OC对象转 ...

  8. MapReduce和Hadoop流

    MapReduce:分布式计算的框架 MapReduce是一个软件框架,可以将单个计算作业分配给多台计算机执行. MapReduce在大量节点组成的集群上运行.它的工作流程是:单个作业被分成很多小份, ...

  9. 【2018.10.2】Note of CXM

    1.有一张无向图,现在要给每个点染上黑色或白色,最后每个点的染色代价是它与离这个点最近的不同色节点的距离.求最小代价.所有边权$\geq 0$且互不相同. 分三种情况: 两点都染了色:两点都跟其它点算 ...

  10. java面试题之简单介绍一下集合框架

    集合框架分为三块:List列表.Set集合.Map映射 List列表在数据结构上可以被看做线性表,常用的有ArrayList和LinkList(不常用的有Vector(类似于ArrayList)),他 ...