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

时间:2012-05-27 05:17:50

标签: c++ string pointers const printf

我在这里缺少什么?这让我疯了!

我有一个返回 const 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 无法正常工作......

3 个答案:

答案 0 :(得分:9)

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

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];
    ....

答案 1 :(得分:5)

在这两种情况下,它都会调用未定义的行为,因为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)的好处(和美)是你不必提前知道输出的大小,这意味着你不必使用幻数例如数组声明10中的char s[10]。从这个意义上讲,这些课程是安全的。

答案 2 :(得分:1)

char s[10]中的

Notation被置于堆栈中,因此在退出Notation函数后会被销毁。这些变量称为automatic。您需要使用new

将字符串保存在堆中
char *s = new char[10];

但你必须手动释放这个记忆:

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

如果您真的使用C ++,那么请使用内置的stringNawaz建议。如果以某种方式限制为原始指针,则在Notation之外分配缓冲区并将其作为 destanation 参数传递,如sprintfstrcat