• 数字数据类型及其对应转移字符


    说明: 

    格式字符:c   输出一个字符。

         s   输出一个字符串。

         e   以指数形式输出实型数。

         f     以小数形式输出实型数。

         g   自动决定输出格式为e和f中较短的一种,不打印无效的零。

         %   输出%。

     

    注意:对于单精度数,使用 %f 格式符输出时,仅前7位是有效数字,小数6位。

       对于双精度数,使用 %lf 格式符输出时,前16位是有效数字,小数6位。

     

    长度修正符

      l:对整型指定长整型long

          例:%ld , %lx , %lo , %lu

        对实型指定双精度double

               例:%lf

        h:只用于整型的格式字符修正为short

               例:%hd , %hx , %ho , %hu

    格式输出字符:printf

    使用:向终端输出若干个类型任意的数据。

    形式:printf (格式控制符,输出列表)

    说明:

    格式控制符:%  格式说明引导符。

          -  指定左对齐输出。

          0  指定空位填零。

          m.n 指定输出域宽度及精度。

          l.h 输出长度的修正。

         格式字符   指定输出的数据类型。

    说明:

    格式字符:指定输出项的数据类型和输出格式。

         d  有符号十进制整数。

         o  无符号八进制数。

         x  无符号十六进制数。(小写的x格式中用小写字母a,b,c,d,e,f来表示10到15之间的数,大写的X则用大写的ABCDEF来表示10到15之间的数)

         u  不带符号的十进制整数。

     

    http://blog.csdn.net/yahohi/article/details/7701434

     

    1. printf("%f ",5);  
    2. printf("%d ",5.01);   
    3. printf("%f ", (float)5);    
    4. printf("%f ", 5.f);    


    输出结果:

    看到结果,会感觉非常奇怪。1处怎么会输出0呢?2又为何会显示这么大的一个数呢?

    解释:

    下面是转自网上的一篇博客的解释

    1,之所以没输出5,这是C语言设计的原因。
    2,之所以输出0,这是计算机体系结构的问题。

    具体来说:

    printf函数不会进行任何类型转换,它只是从内存中读出你所提供的元素的值(按照%d,%f等控制字符提示的格式)。C语言设计中,int类型一般是32bit或者16bit,而float一般是64bit,并且有可能使用科学计数保存。这点就和huhugo88所说一样,5在内存中为00000000,00000101。而且5一般都在静态区,程序的静态存储区默认是0,那么当用%f来读时,就会读64bit,也就是会读之前的很多位0,最后按照(有效数字)×(基数2)pow(指数)的方式来取数,自然结果是0

    之所以Vc中不允许这种情况,而有些编译器就允许这么输出就是编译器设置的问题。按理说,这样访问内存是属于越界访问,应该禁止。不过只是读,伤害性不大而已。  对于单精度浮点数(32bit),不少c语言编译系统以24位表示小数部分(包括1bit符号位),以8位表示指数部分。 ==========================printf("%d ",5.01);  为什么输出一个大数?在讲这个题目之前,预备知识,讲一下,printf函数,输入参数是读入缓冲区保存,再按照%?的格式从缓冲区中读出数据,并据此格式解释数据。

    有了这个知识之后,在讲程序员面试宝典上看到一个题:

    #include "stdio.h" 
    int main(int argc, char* argv[])   
    {   
        printf("%d ",5.01);   
    return 0;   
    }   
    输出结果为:188978561  
    然后开始研究为什么会是这个数?

    5.01是double类型,内存中占8个字节,保存在缓冲区。而%d为整型,占4个字节,printf从缓冲区中读入4字节,先读到低32位的数据。也就是说printf输出的应该是5.01以double类型保存数剧的低32位。为了检验此结果是否正确,对比5.01在内存中的表示与输出。

    #include "stdio.h" 
    int main(int argc, char* argv[])   
    {   
    double d = 5.01;   
    int *p = (int *)(&d);   
    int rst = 1889785610;   
        printf("1).%x ",*p);   
        printf("2).%x ",*(p+1));   
        printf("3).%x ",rst);   
    return 0;   
    }   
    输出为:   
    1).0x70a3d70a   
    2).0x40140a3d   
    3).0x70a3d70a  
    这也就证明了%d输出了5.01的低32低。5.01的double类型,在内存的的表示为0x40140a3d70a3d70a。

    事情看似也就完成了。

    我又想,如果输入是浮点类型的5.01f,又会发生什么呢?

    #include "stdio.h" 
    int main(int argc, char* argv[])   
    {   
    float f = 5.01f;     
    int *p = (int *)(&f);        
        printf("1).0x%x ",*p);     
        printf("2).0x%x ",5.01f);     
    return 0;     
    }   
    输出:   
    1).0x40a051ec   
    2).0x80000000  
    我们发现,此时输出的并不是浮点类型5.01f的内存的表示,这是为什么呢?

    然后看到一个说法,是printf会把%f按double类型输出,也就是说会把参数float型的转成double型在输出。

    但现在并不是%f,当然用%f显示的是正确的结果。于是我猜测,printf是将所在float型读入的数据都自动的转化为double型了,然后%f就按double处理,而我们这是%d,所以显示的为float转化为double型后的低4字节。

    验证此想法:

    #include "stdio.h" 
    int main(int argc, char* argv[])   
    {   
    double f = 5.01;     
    int *p = (int *)(&f);   
        printf("1).0x%x ",*p);   
        printf("2).0x%x ",*(p+1));     
        printf("3).0x%x ",5.01f);     
    return 0;     
    }   
    输出:   
    1).0x70a3d70a   
    2).0x40140a3d   
    3).0x80000000  
    但是我们发现结果并不一样,于是我又猜想,也是许printf将float转化为double的方式与默认的方式不一样

    5.01d的默认的表示为:0x40140a3d70a3d70a,在上面已经说明了

    #include "stdio.h" 
    int main(int argc, char* argv[])   
    {   
        printf("0x%8x 0x%8x ",5.01f);   
    return 0;   
    }   
    输出为:   
    0x80000000   
    0x40140a3d  
    与是发现printf将5.01f->5.01d的表示是:0x40140a3d80000000

    接着就是看这两个值是否都是为5.01了:

    view plaincopy to clipboardprint?

    #include "stdio.h" 
    int main(int argc, char* argv[])   
    {   
    int d1[2], d2[2];   
        d1[0]=0x80000000;   
        d1[1]=0x40140a3d;   
        d2[0]=0x70a3d70a;   
        d2[1]=0x40140a3d;   
    double *p1 = (double *)d1;   
    double *p2 = (double *)d2;   
        printf("1).%f ",*p1);   
        printf("2).%f ",*p2);   
    return 0;     
    }   
    输出为:   
    1).5.010000   
    2).5.010000  
    也就证明了0x40140a3d80000000,与0x40140a3d70a3d70a都是5.01d在机器中的表示。前者为5.01f(0x40a051ec)由printf转化为double后的表示,后者为5.01d的默认的表示。

    总结:printf将输的浮点型参数全都自动转化为双精度型,且与默认的双精度的表示方法是不同的。最重要一点,printf不安全,类型不安全,要是类型不对了,也许我们就挂了^_^


    printf("%d",5.01)和printf("%f",5)的输出结果

    通过以上解释,我们大致明白:

    1. printf输出float型时,会自动转化成double型;

    2. 由于存储时,都是先低位,再高位,同时经过转化成double,前面会取很多0(越界访问);

    3. 5.01,打印时按照int来取,只取前四个字节。

  • 相关阅读:
    ARPPING
    Oracle RAC 连接
    Win7 DCOM 配置中我的电脑出现红色箭头并且无属性显示的解决方法
    Ping命令
    Linux & Oracle 安装目录说明
    TCP 四次握手
    wireshark使用
    jcaptcha组件小小改造解决Invalid ID, could not validate une
    JustSniffer
    java 自己定义异常,记录日志简单说明!留着以后真接复制
  • 原文地址:https://www.cnblogs.com/chengxuyuandashu/p/3562283.html
Copyright © 2020-2023  润新知