C++:C 字符串到 std:string

C++: C string to std:string

我正在尝试使用函数将 C 字符串转换为 std::string。该函数在 64 位 gcc (GCC) 4.8.3 20140911 (Red Hat 4.8.3-9) 上正常工作。但是当我用 -O2-O3 优化编译它时,它会出现段错误。它适用于 -O1 不过。有人可以建议修复或解决这个问题吗?函数如下:

void make_name(unsigned const &i, string &h_file)
{
        char h_str[10];
        sprintf(h_str, "tmp/%09d.hb", i);
        h_file = string(h_str);
}

简单:提供足够的缓冲。或者使用 std::stringstream

char h_str[10];
sprintf(h_str, "tmp/%09d.hb", i);

这是未定义的行为。您正在尝试将大约 17 个字节的数据写入一个 10 字节的数组:

  • tmp/ 是四。
  • %09d 将至少扩展到九个。
  • .hd 是三.
  • 字符串终止符[=15=]是一个。

不要那样做。未定义的行为意味着所有功能保证都是无效的。


事实上,如果你想成为一个真正体面的 C++ 开发人员,你应该尽可能地避免遗留的东西。

学习和库代码都很好,需要 运行 在 C 和 C++ 中。但是,对于 C++ 代码,使用该语言的非遗留部分要健壮得多。

下面的程序展示了如何做到这一点而不必恢复到cstdio/stdio.h中的遗留 C 语言:

#include <iostream>
#include <iomanip>
#include <sstream>

using namespace std;

void make_name (unsigned int i, string &h_file) {
    stringstream ss;
    ss << "tmp/" << setw(9) << setfill('0') << i << ".hb";
    h_file = ss.str();
}


int main() {
    string s;
    make_name (42u, s);
    cout << s << '\n';
    return 0;
}

As an aside, you'll see I've changed your method signature to pass i by value. That's because I'm not sure there's any advantage to doing it as a const reference. Feel free to change it back if you do find an advantage.

最好永远不要使用 C 字符串。

std::string make_name(unsigned i)
{
    std::ostringstream str;
    str << "tmp/" << std::setfill('0') << std::setw(9) << i << ".hb";
    return std::move(str.str());
}