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