• sprintf函数你了解有多深!


    1、在使用每一个函数时都要注意任何一个微小的细节。同一个函数的使用,高手可以控制的很好。我是菜鸟,所以范了下面的错误。
       int sprintf(char *, const char *, ...),
       int sscanf(const char *, const char *, ...)
    注意了么,里面的参数是char*型的,也就是字符串。
    看下面的一段程序:
    在VC6.0下,控制台程序,在属性页中使用MFC。
    #include <stdio.h>
    #include <afx.h>
    typedef unsigned char byte;
    void main()
    {
    byte len[4]={0};
    byte length[8]={0};
    sprintf((char *)len,"%04X",4); //1
    sprintf((char *)length,"B%cB%cB%cB%c",len[3],len[2],len[1],len[0]);//2
    sscanf((const char *)length,"%2x%2x%2x%2x",&len[0],&len[1],&len[2],&len[3]);//3
    }

    大家看这段程序是否有问题?
    回答是肯定的,但它在你的机子上跑可能没问题,这要看地址是如何分配的。如果len和length的地址是紧挨着的,那就要出问题了。
    在我的机器上运行时,会出现这个程序出现问题了,你是否发送报告这样的错误。
    跟踪一下,可以看到len的地址是0x0012ff7c,length的地址是0x0012ff74。可以看出两者之间的字节正好是8个,而这8个字节是存放length中的元素的。
    在程序中,我们好像控制的非常好,没有出现溢出的情况。但事实上是溢出了,我们可以在1、2、3处加上输出语句,注意绝对不能用printf("%s",len)的形式输出,以为我们没让len存放'\0'。程序如下:
    #include <stdio.h>
    #include <afx.h>
    typedef unsigned char byte;
    void main()
    {
       byte len[4]={0};
       byte length[8]={0};
       int i;

       sprintf((char *)len,"%04X",4);
       for(i=0; i<4; i++) //1
        printf("%4c",len[i]);
       printf("\n");

       sprintf((char *)length,"B%cB%cB%cB%c",len[3],len[2],len[1],len[0]);
         for(i=0; i<4; i++) //2
        printf("%4c",len[i]);
       printf("\n");
      
       sscanf((const char *)length,"%2x%2x%2x%2x",&len[0],&len[1],&len[2],&len[3]);
       for(i=0; i<8; i++) //3
        printf("%4c",length[i]);
       printf("\n");
    }
    结果中1,3处都是正确的,而2处结果是不对了。结果如下图

    为什么呢?该到关键处了。
    在第一个sprintf执行前时,74-7f中的值都为0,*代表未知。在第一个sprintf执行完后,在内存中的形式是

    length                                        len
    0x0012ff74 75   76   77   78   79   7a   7b   7c   7d   7e   7f   80   81
                                                  0    0    0    4    NULL *
    注意到80位置处变为0了么。这是关键啊!sprintf执行时,后面自动把后面的一个字节变为NULL。
    在执行完第二条语句后,内存形式为

    length                                        len
    0x0012ff74 75   76   77   78   79   7a   7b   7c   7d   7e   7f   80   81
    B        4    B    0    B    0    B    0    NULL 0    0    4    0    *
    注意到len的起始地址变为NULL了么,这是程序出错的根本。

    若是len和length的地址不紧挨着就没事了(就本程序来说,不是绝对的)。我们可以刻意不让他们的地址挨着。程序如下:
    #include <stdio.h>
    #include <afx.h>
    typedef unsigned char byte;
    void main()
    {
       byte A[10];
       byte len[4]="";
       byte B[10];
       byte length[8]={0};
       byte C[10];
       sprintf((char *)len,"%04X",4);
       sprintf((char *)length,"B%cB%cB%cB%c",len[3],len[2],len[1],len[0]);
        sscanf((const char *)length,"%2x%2x%2x%2x",&len[0],&len[1],&len[2],&len[3]);

    }
    运行就不会有问题了,但这没有解决问题的关键。

    总结:
    在上面的问题中,sprintf中的第一个参数是char*的形式。将后面的变量变为字符串时,后面需要加NULL的。在这由于是 sprintf((char*)len,"%04",4),%04使0004占满了len中的所有空间,所以将len空间后的内存变为了NULL。而变为 NULL的这个字节正好是导致错误出现的区域,因为它不在我们的控制范围之内。
    要解决,就是把len和length多分配一个空间,使他们在我们的控制之下就安全了。

    最后说一下,单纯看这个程序,大家可能很快找到错误发生在哪。但是对于一个工程,要是出现这样的错误,恐怕你得调一阵了。所以还请大家多多积累,掌握每个细节。高手就是能抓住每个细节,看似都会的东西,就看你能理解到多深,多透了。

    说的不对的地方,请大家多多指教。
  • 相关阅读:
    dubbo服务配置
    架构基本概念和架构本质
    最大子数组和问题
    struts2简单登陆页面
    四则运算随机出题
    省赛训练赛赛题(简单题)
    Ubuntu虚拟机安装,vritualbox虚拟机软件的使用
    Rational Rose 2007破解版
    netbeans出现的错误
    快速幂
  • 原文地址:https://www.cnblogs.com/danghuijian/p/4400877.html
Copyright © 2020-2023  润新知