加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

基础研究--为什么scanf类型不安全

(2010-01-01 15:45:17)
标签:

scanf

类型

不安全

it

     在effective C++中第二节中,scott meyer说C语言中的scanf/printf是类型不安全的,而iostream中的>>, <<是类型安全的。

下了gcc4.4.1解压。在libstdc++-v3/include/c中,找到#undef scanf, 点击,用sourceinsight可找到其类型的地方,其中有一个

extern USE_SCANF(1,2) int scanf_gnu (const char *restrict, ...);

#undef scanf

#define scanf scanf_gnu

说明scanf实际上是调用的scanf_gnu, 此函数估计是在操作系统内核中实现。其参数也带

“const char *restrict“无法从源码中找原因

 

  打开vc6.0,

运行一段程序

#include <stdio.h>

Int main(void)

{

       Double I;

       Scanf(“%d”, &i);

       Printf(“%f”, i);

       Return 0

}

 

输入5.1, 输出0.0000

说明,scanf处理的方式是,接收终端,然后将其格式化为格式内容。而格式时,如果类型不匹配,则会为0.000, 而不报错。

 

对于libstdc++-v3/include/std/istream, 看它的类声明

template<typename _CharT, typename _Traits>

    class basic_istream : virtual public basic_ios<_CharT, _Traits>

    {

    public:

      // Types (inherited from basic_ios (27.4.4)):

      typedef _CharT                             char_type;

      typedef typename _Traits::int_type          int_type;

      typedef typename _Traits::pos_type         pos_type;

      typedef typename _Traits::off_type         off_type;

      typedef _Traits                              traits_type;

     

      // Non-standard Types:

      typedef basic_streambuf<_CharT, _Traits>             __streambuf_type;

      typedef basic_ios<_CharT, _Traits>         __ios_type;

      typedef basic_istream<_CharT, _Traits>          __istream_type;

      typedef num_get<_CharT, istreambuf_iterator<_CharT, _Traits> >       

                                                __num_get_type;

      typedef ctype<_CharT>                                __ctype_type;

 

    protected:

      // Data Members:

     

      streamsize         _M_gcount;

 

    public:

      // [27.6.1.1.1] constructor/destructor

     

      explicit

      basic_istream(__streambuf_type* __sb)

      : _M_gcount(streamsize(0))

      { this->init(__sb); }

 

      

      virtual

      ~basic_istream()

      { _M_gcount = streamsize(0); }

 

      // [27.6.1.1.2] prefix/suffix

      class sentry;

      friend class sentry;

 

      // [27.6.1.2] formatted input

      // [27.6.1.2.3] basic_istream::operator>>

      //@{

     

      __istream_type&

      operator>>(__istream_type& (*__pf)(__istream_type&))

      { return __pf(*this); }

 

其中它的operator>>重载函数,里面的实现是

      __istream_type&

      operator>>(__istream_type& (*__pf)(__istream_type&))

      { return __pf(*this); }

它的参数是一个函数指针,并且类数是__istream_type, 即basic_istream<_CharT, _Traits>

对于return __pf(*this), _pf是什么就不知道了。

 

其中还有成员

      typedef _CharT                             char_type;

      typedef typename _Traits::int_type          int_type;

      typedef typename _Traits::pos_type         pos_type;

      typedef typename _Traits::off_type         off_type;

      typedef _Traits                              traits_type;

这个是用于翠取类型的结构体。想必C++中的安全性是要将_Traits::value_type与输入的类型进行比较,若不相同则报错

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有