使用libc和libstdc的void *类型的stringstream行为的差异

以下测试程序返回不同的结果,具体取决于我使用的是libc还是libstdc.
#include <sstream>
#include <iostream>

int main()
{
    int a = 0;
    void* optr = &a;
    void* iptr;

    std::stringstream ss;
    ss << optr;
    std::cout << ss.str() << '\n';

    ss >> iptr;
    std::cout << iptr << '\n';

    return 0;
}

我在OSX 10.9.2上使用Xcode 5的以下版本的clang

$xcrun clang++ --version              
Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin13.1.0
Thread model: posix

这是使用libstdc和libc构建时的测试输出

$xcrun clang++ test.cpp  <-- libstdc++ version             
$./a.out
0x7fff5ec723e8
0x7fff5ec723e8
$xcrun clang++ test.cpp -stdlib=libc++  <-- libc++ version
$./a.out
0x7fff5205125c
0x7fff5

这是stringstream的libc实现中的错误吗?使用void *与stringstream有效C吗?

谢谢!

解决方法

是!它是libc中的一个错误,可能是在__sscanf_l的实现中(某些scanf看起来应该考虑区域设置). libstdc实现更简单.
// libc++

template <class _CharT,class _InputIterator>
_InputIterator
num_get<_CharT,_InputIterator>::do_get(iter_type __b,iter_type __e,ios_base& __iob,ios_base::iostate& __err,void*& __v) const
{
    // Stage 1
    int __base = 16;
    // Stage 2
    char_type __atoms[26];
    char_type __thousands_sep = 0;
    string __grouping;
    use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,__num_get_base::__src + 26,__atoms);
    string __buf;
    __buf.resize(__buf.capacity());
    char* __a = &__buf[0];
    char* __a_end = __a;
    unsigned __g[__num_get_base::__num_get_buf_sz];
    unsigned* __g_end = __g;
    unsigned __dc = 0;
    for (; __b != __e; ++__b)
    {
        if (__a_end == __a + __buf.size())
        {
            size_t __tmp = __buf.size();
            __buf.resize(2*__buf.size());
            __buf.resize(__buf.capacity());
            __a = &__buf[0];
            __a_end = __a + __tmp;
        }
        if (this->__stage2_int_loop(*__b,__base,__a,__a_end,__dc,__thousands_sep,__grouping,__g,__g_end,__atoms))
            break;
    }
    // Stage 3
    __a[sizeof(__a)-1] = 0;
#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
    if (sscanf_l(__a,_LIBCPP_GET_C_LOCALE,"%p",&__v) != 1)
#else
    if (__sscanf_l(__a,__cloc(),&__v) != 1)
#endif
        __err = ios_base::failbit;
    // EOF checked
    if (__b == __e)
        __err |= ios_base::eofbit;
    return __b;
}

// libstdc++

template<typename _CharT,typename _InIter>
_InIter
num_get<_CharT,_InIter>::
do_get(iter_type __beg,iter_type __end,ios_base& __io,void*& __v) const
{
  // Prepare for hex formatted input.
  typedef ios_base::fmtflags        fmtflags;
  const fmtflags __fmt = __io.flags();
  __io.flags((__fmt & ~ios_base::basefield) | ios_base::hex);

  typedef __gnu_cxx::__conditional_type<(sizeof(void*)
                     <= sizeof(unsigned long)),unsigned long,unsigned long long>::__type _UIntPtrType;       

  _UIntPtrType __ul;
  __beg = _M_extract_int(__beg,__end,__io,__err,__ul);

  // Reset from hex formatted input.
  __io.flags(__fmt);

  __v = reinterpret_cast<void*>(__ul);
  return __beg;
}

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...