【问题标题】:fprintf has problems with characters returned by a functionfprintf 函数返回的字符有问题
【发布时间】:2017-03-01 16:18:19
【问题描述】:

我有两个问题。两者都可以用这个简单的代码来说明(用 g++ -Wall -O2 -std=c++14 编译):

#include <string>
using namespace std;

const char *printi(const unsigned long &i) {
    return to_string(i)).c_str();
}

int main() {    
    unsigned long i1 = 1; unsigned long i2 = 2;
    fprintf(stderr, "%s%s\n", printi(i1), printi(i2));
}

问题编号。 1 - 它打印“11”,而它应该打印“12”。

问题编号。 2 - 有时它根本不打印数字,而是打印一些奇怪的字符。

【问题讨论】:

  • 有趣的是,当我运行此代码时,我得到 22 作为输出。为什么要打印到stderr 而不是stdout
  • 您返回的是一个临时 = 坏消息。
  • 如果我不能使用函数返回的值,我该如何工作? :( 我需要将该字符串放入 fprintf ... (整个代码只是对更大的东西的抽象,这应该是调试信息,这就是它是 stderr 的原因)
  • @Jecke:你在写 C 还是 C++?使用std::string,如果你正在编写C++,使用std::cerr
  • 我用 C++ 编写,但我使用 fprintf 因为它更方便。我可以使用fprintf("blah %s blah %lu blah %s\n", a, b, c) 而不是cerr &lt;&lt; "blah" &lt;&lt; a &lt;&lt; "blah" &lt;&lt; b &lt;&lt; "blah" &lt;&lt; c &lt;&lt; endl;... 它更短更灵活。事实上,我一开始就有#define debug_out( ... ) if (debug) fprintf(stderr, __VA_ARGS__ ),我不必担心要打印多少不同的参数,而且它更干净

标签: c++ char printf


【解决方案1】:

注意std::to_string() 返回一个std::string。这个std::string只存在于printi()函数作用域之内,也就是说当你退出函数时(当你return时),这个std::string的析构函数被调用,你返回的地址(由c_str()) 不再指向有效内存。您的代码具有未定义的行为,因为您不知道它现在指向哪个数据。

为了解决这个问题,你可以让printi()返回一个std::string,它会在return上被深度复制到调用者中,然后调用者可以根据需要使用c_str()

#include <string>
using namespace std;

string printi(const unsigned long &i) {
    return to_string(i);
}

int main() {    
    unsigned long i1 = 1; unsigned long i2 = 2;
    fprintf(stderr, "%s%s\n", printi(i1).c_str(), printi(i2).c_str());
}

【讨论】:

  • 是的。固定的。谢谢。
  • 嗯...所以如果我创建一个函数 int return5() { short a = 5;返回一个; },我不能指望 cout
  • "为了修复它,您可以返回对 std::string 的引用" -- 听起来您建议用悬空引用替换悬空指针。如果没有,我不确定你在这里建议什么。
  • 这实际上会起作用,当您返回一个对象 (char*, int) 时,它只是被复制,对于 int 它将复制其数据,对于 char* 它将复制其地址。如果你返回 std::string 它也会复制它的数据但是当你退出作用域时,析构函数被调用,现在 c_str 字符串的地址不再有效,内存被清理了!现在你手里拿着无效的地址并尝试打印它。
  • @Jecke:更好的类比是,如果您创建了这样的函数:int* return5() { int a = 5; return &amp;a; }——在这种情况下,您无法保证cout &lt;&lt; *return5(); 将打印 5。
猜你喜欢
  • 2013-11-25
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
  • 2015-08-24
  • 1970-01-01
  • 2017-04-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多