C++ : 为什么我不能使用 sprintf 打印 const 字符*?



我在这里错过了什么?快把我逼疯了!

我有一个返回常量字符* 的函数

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

在这里,s从函数Notation()返回后不会存在。如果您不关心线程安全,则可以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++流用作:

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

然后:

char str[50];       
sprintf(str, "%s", Notation().c_str());

std::ostringstream(和std::string)的好处(和美感)是你不必提前知道输出的大小,这意味着你不必在数组声明char s[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++那么像纳瓦兹建议的那样使用内置string类。 如果您以某种方式限制为原始指针,请在Notation外部分配缓冲区并将其作为 destanation 参数传递,如 sprintfstrcat .

最新更新