C++ C++;:为什么我能';不能用sprintf打印常量字符*?

C++ C++;:为什么我能';不能用sprintf打印常量字符*?,c++,string,pointers,constants,printf,C++,String,Pointers,Constants,Printf,我错过了什么?它快把我逼疯了 我有一个函数,它返回一个常量char* const char* Notation() const { char s[10]; int x=5; sprintf(s, "%d", x); return s; } 现在,在代码的另一部分中,我正在这样做: ..... ..... char str[50]; sprintf(str, "%s", Notation()); ..... ..... 但是str保持不变 如果我这

我错过了什么?它快把我逼疯了

我有一个函数,它返回一个常量char*

const char* Notation() const
{
    char s[10];
    int x=5;
    sprintf(s, "%d", x);
    return s;
}
现在,在代码的另一部分中,我正在这样做:

.....
.....
char str[50];       
sprintf(str, "%s", Notation());
.....
.....
但是str保持不变

如果我这样做:

.....
.....
char str[50];
str[0]=0;
strcat(str, Notation());
.....
.....
str设置正确


我想知道为什么sprintf不能按预期工作…

您试图返回在堆栈上分配的数组,但其行为未定义

const char* Notation() const
{
    char s[10];
    int x=5;
    sprintf(s, "%d", x);
    return s;
}
从函数
Notation()
返回后,
s
将不会出现在这里。如果您不关心线程安全,则可以将
s
设置为静态

const char* Notation() const
{
    static char s[10];
    ....

在这两种情况下,它都会调用未定义的行为,因为
Notation()
返回一个本地数组,该数组在返回时会被销毁。不幸的是,它在一种情况下起作用,让你觉得它是正确的

解决方案是将
std::string
用作:

std::string Notation() const
{
    char s[10];
    int x=5;
    sprintf(s, "%d", x);
    return s; //it is okay now, s gets converted into std::string
}

或使用C++流AS:

std::string Notation() const
{
    int x=5;
    std::ostringstream oss;
    oss << x;
    return oss.str(); 
}

std::ostringstream
(和
std::string
)的好处(和优点)是您不必事先知道输出的大小,这意味着您不必在数组声明
char[10]
中使用幻数,例如
10
。从这个意义上讲,这些类是安全的。

Notation
中的char s[10]被放置在堆栈上,因此它在退出
Notation
函数后被销毁。这样的变量称为。您需要使用
new
将字符串保存在堆中:

char *s = new char[10];
但您必须手动释放此内存:

char str[50];
const char *nt = Notation();
sprintf(str, "%s", nt);
printf("%s", str);
delete[] nt;

如果你真的使用C++,那么使用内置的代码>字符串类,如建议的。如果您以某种方式限制了原始指针,那么在

表示法
之外分配缓冲区,并将其作为destantation参数传递,如
sprintf
strcat

中,我认为缓冲区是在编译时分配的,并在应用程序的生命周期内一直保持在那里。如果这不是真的,那么这是否意味着每个返回非全局常量char*的函数都是错误的?(和危险)任何返回自动常量字符*的函数都是危险的。还有许多其他返回缓冲区的方法,例如静态的和使用malloc新分配的缓冲区。但是,如果返回malloc'd缓冲区,则必须正确管理清理。@Wartin:我认为您考虑的是字符串文字。例如,如果您说:
返回“foobar”--这是安全的,因为字符串“foobar”会在应用程序的整个生命周期内持续。@hawk:您认为使缓冲区保持静态可以完成这项工作吗?我不关心线程安全(但我想知道为什么它很重要;-)@Wartin-粗略地说,函数中的静态会将变量的生命周期延长到程序结束。然而,可见性就像一个自动变量。它不是线程安全的原因很简单,就是多线程可以在函数中并发执行,并且可以相互作用。虽然这可以解决问题,但这是一个糟糕的想法。如果他试图以现在的方式使用该函数,那么肯定会出现内存泄漏。是的,就是这样。既然问题是关于C++的,那么<>代码> string < /C>是最好的选择。也许有一个想法是将函数改为:空符号(char *缓冲)const,并在调用方提供的char缓冲区工作。为什么要投票?问题很清楚,给出了一个“工作”样本,显示了努力程度,并给出了实际问题样本。
char str[50];
const char *nt = Notation();
sprintf(str, "%s", nt);
printf("%s", str);
delete[] nt;