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

前端之家收集整理的这篇文章主要介绍了使用libc和libstdc的void *类型的stringstream行为的差异前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
以下测试程序返回不同的结果,具体取决于我使用的是libc还是libstdc.
  1. #include <sstream>
  2. #include <iostream>
  3.  
  4. int main()
  5. {
  6. int a = 0;
  7. void* optr = &a;
  8. void* iptr;
  9.  
  10. std::stringstream ss;
  11. ss << optr;
  12. std::cout << ss.str() << '\n';
  13.  
  14. ss >> iptr;
  15. std::cout << iptr << '\n';
  16.  
  17. return 0;
  18. }

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

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

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

  1. $xcrun clang++ test.cpp <-- libstdc++ version
  2. $./a.out
  3. 0x7fff5ec723e8
  4. 0x7fff5ec723e8
  5. $xcrun clang++ test.cpp -stdlib=libc++ <-- libc++ version
  6. $./a.out
  7. 0x7fff5205125c
  8. 0x7fff5

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

谢谢!

解决方法

是!它是libc中的一个错误,可能是在__sscanf_l的实现中(某些scanf看起来应该考虑区域设置). libstdc实现更简单.
  1. // libc++
  2.  
  3. template <class _CharT,class _InputIterator>
  4. _InputIterator
  5. num_get<_CharT,_InputIterator>::do_get(iter_type __b,iter_type __e,ios_base& __iob,ios_base::iostate& __err,void*& __v) const
  6. {
  7. // Stage 1
  8. int __base = 16;
  9. // Stage 2
  10. char_type __atoms[26];
  11. char_type __thousands_sep = 0;
  12. string __grouping;
  13. use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,__num_get_base::__src + 26,__atoms);
  14. string __buf;
  15. __buf.resize(__buf.capacity());
  16. char* __a = &__buf[0];
  17. char* __a_end = __a;
  18. unsigned __g[__num_get_base::__num_get_buf_sz];
  19. unsigned* __g_end = __g;
  20. unsigned __dc = 0;
  21. for (; __b != __e; ++__b)
  22. {
  23. if (__a_end == __a + __buf.size())
  24. {
  25. size_t __tmp = __buf.size();
  26. __buf.resize(2*__buf.size());
  27. __buf.resize(__buf.capacity());
  28. __a = &__buf[0];
  29. __a_end = __a + __tmp;
  30. }
  31. if (this->__stage2_int_loop(*__b,__base,__a,__a_end,__dc,__thousands_sep,__grouping,__g,__g_end,__atoms))
  32. break;
  33. }
  34. // Stage 3
  35. __a[sizeof(__a)-1] = 0;
  36. #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
  37. if (sscanf_l(__a,_LIBCPP_GET_C_LOCALE,"%p",&__v) != 1)
  38. #else
  39. if (__sscanf_l(__a,__cloc(),&__v) != 1)
  40. #endif
  41. __err = ios_base::failbit;
  42. // EOF checked
  43. if (__b == __e)
  44. __err |= ios_base::eofbit;
  45. return __b;
  46. }

  1. // libstdc++
  2.  
  3. template<typename _CharT,typename _InIter>
  4. _InIter
  5. num_get<_CharT,_InIter>::
  6. do_get(iter_type __beg,iter_type __end,ios_base& __io,void*& __v) const
  7. {
  8. // Prepare for hex formatted input.
  9. typedef ios_base::fmtflags fmtflags;
  10. const fmtflags __fmt = __io.flags();
  11. __io.flags((__fmt & ~ios_base::basefield) | ios_base::hex);
  12.  
  13. typedef __gnu_cxx::__conditional_type<(sizeof(void*)
  14. <= sizeof(unsigned long)),unsigned long,unsigned long long>::__type _UIntPtrType;
  15.  
  16. _UIntPtrType __ul;
  17. __beg = _M_extract_int(__beg,__end,__io,__err,__ul);
  18.  
  19. // Reset from hex formatted input.
  20. __io.flags(__fmt);
  21.  
  22. __v = reinterpret_cast<void*>(__ul);
  23. return __beg;
  24. }

猜你在找的C&C++相关文章