以下测试程序返回不同的结果,具体取决于我使用的是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;
- }