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

Convert built-in data type to std::string: memcpy vs snprintf

本文关键字:string memcpy vs snprintf std 内置 置数据 类型转换      更新时间:2023-10-16

我在此之前参考了相关问题和其他帖子。我也知道std::to_string()是最好的方式(但它在少数平台上不可用)。

实验时,我遇到了memcpy()的一个奇怪问题。对于示例,假设我们总是将内置数据类型(int, char, long)传递给下面的函数:

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;
}

在示例程序中单独运行此函数可以正常工作。但是当插入更大的代码库时,不知何故它会给出奇怪的结果!也就是说,它给出了虚假的值。(Ubuntu 14.10, c++ 4.9 -std=c++11)

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

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. 字节顺序会影响这个代码吗?

概括一下,是的,您不希望使用memcpy()。使用snprintf()可以避免自己将数字转换为ASCII。不过,这样的代码可能更可取:

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,您可以使用循环,如下所示:

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 = '';
  do
  {
    *--s = value % 10 + '0';  // conversion to ASCII, 1 digit at a time
    value /= 10;
  }
  while(value > 0);
  return s;
}

警告:该函数不能正确处理负数。我把它作为一个练习,让你根据需要来处理。

现在,如果你想用c++的方式在你提到的所有系统上工作,没有boost或c++ 11。

template<typename T>
std::string to_string (T const& value)
{
  std::stringstream ss;
  ss << value;
  return ss.str();
}

在这种情况下,stringstream知道如何处理T,无论T是什么,数字,对象等,只要这些东西理解<<std::cout << "Hello!" << std::endl;

如果你查看我的一个名为as2js的项目,你会看到一个名为include/as2js/node.h的文件,其中声明如下:

std::ostream& operator << (std::ostream& out, Node const& node);
这意味着您可以稍后创建一个节点并像这样打印它:
Node n;
std::out << n << std::endl;

这意味着to_string()函数将与我的Node对象一起工作。

您可以在lib/node_display.cpp

下找到所有这些的实现