首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将内置数据类型转换为std::string: memcpy vs snprintf

将内置数据类型转换为std::string: memcpy vs snprintf
EN

Stack Overflow用户
提问于 2014-08-08 11:06:18
回答 1查看 1.2K关注 0票数 0

在此之前,我已经提到过相关问题和其他帖子。我也意识到std::to_string()是最好的方法(但它在少数平台上是不可用的)。

experimenting,遇到memcpy()时,我遇到了一个奇怪的问题。为了示例起见,假设我们总是将内置数据类型(intcharlong)传递给下面的函数:

代码语言:javascript
复制
template<typename T>
std::string to_string (const T& value)
{
  std::string s(16, 0); // Max size captured
  ::memcpy(&s[0], &value, sizeof(value));
  return s;
}

在示例程序中单独运行此函数可以工作得很好。但是,当插入一个更大的代码库时,不知怎么的,它会产生奇怪的结果!也就是说,它提供了虚假的值。(Ubuntu14.10,g++4.9 -std=c++11)

但是,如果我使用sprintf()来转换上面的程序,它就会工作得很好。

代码语言:javascript
复制
template<typename T>
std::string to_string (const T& value)
{
  std::string s(16, 0); // Max size captured
  s[::snprintf(&s[0], "%d", value)] = 0;
  return s;
}

问题

  1. 我是否接触到了memcpy() (甚至sprintf())中未定义的行为?
  2. 字节排序会影响这段代码吗?
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-08-09 01:40:48

简单地说,是的,您不想使用memcpy()。使用snprintf(),您不必自己将数字转换为ASCII。不过,像这样的事情可能更可取:

代码语言:javascript
复制
template<typename T>
std::string to_string (const T& value)
{
  char buf[16];
  ::snprintf(buf, sizeof(buf), "%d", value);
               // ^-- size was missing in your example
  return buf;
}

但是,这个函数有一个很大的流,因为你不知道T会是什么。它可能是双倍的,而且"%d"不会像预期的那样工作。类似地,它可以是一个字符串(char const *)。

如果要手动将数字转换为ASCII,可以使用循环,如下所示:

代码语言:javascript
复制
template<typename T>
std::string to_string (T value)
{
  char buf[16]; // any int number is less than 16 characters
  char *s = buf + sizeof(buf);
  *--s = '\0';
  do
  {
    *--s = value % 10 + '0';  // conversion to ASCII, 1 digit at a time
    value /= 10;
  }
  while(value > 0);
  return s;
}

警告:该函数不能正确处理负数。我会让这件事做个练习,你可以根据需要来处理。

现在,如果您想使用一种C++方式,它应该可以在您提到的所有系统上工作,而不需要boost或C++11。

代码语言:javascript
复制
template<typename T>
std::string to_string (T const& value)
{
  std::stringstream ss;
  ss << value;
  return ss.str();
}

在这种情况下,只要这些东西理解<< (在std::cout << "Hello!" << std::endl;中),字符串流就知道如何处理T--不管T是什么、数字、对象等等。

如果您签出我的一个名为as2js的项目,您将看到一个名为include/as2js/node.h的文件声明如下所示:

代码语言:javascript
复制
std::ostream& operator << (std::ostream& out, Node const& node);

这意味着您以后可以创建一个节点并按如下方式打印它:

代码语言:javascript
复制
Node n;
std::out << n << std::endl;

这意味着您的to_string()函数将使用我的Node对象。

您可以在lib/nodedisplay.cpp下找到所有这些的实现。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25202083

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档