简体   繁体   中英

C++ : Why I can't print a const char* with sprintf?

What am I missing here ? It's driving me nuts !

I have a function that returns a const char*

const char* Notation() const
{
    char s[10];
    int x=5;
    sprintf(s, "%d", x);
    return s;
}

Now in another part of the code I am doing this :

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

but str remains unchanged.

If instead I do this :

.....
.....
char str[50];
str[0]=0;
strcat(str, Notation());
.....
.....

str is correctly set.

I am wondering why sprintf doesn't work as expected...

You're trying to return an array allocated on stack and its behaviour is undefined.

const char* Notation() const
{
    char s[10];
    int x=5;
    sprintf(s, "%d", x);
    return s;
}

here s isn't going to be around after you've returned from the function Notation() . If you aren't concerned with thread safety you could make s static.

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

In both cases, it invokes undefined behavior, as Notation() returns a local array which gets destroyed on returning. You're unlucky that it works in one case, making you feel that it is correct.

The solution is to use std::string as:

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
}

Or using C++ stream as:

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

and then:

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

The benefit (and beauty) of std::ostringstream (and std::string ) is that you don't have to know the size of output in advance, which means you don't have to use magic number such as 10 in array declaration char s[10] . These classes are safe in that sense.

char s[10] in Notation is placed on stack so it gets destroyed after exit from Notation function. Such variables are called automatic . You need to save your string in heap using new :

char *s = new char[10];

But you have to free this memory manually:

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

If you really use C++ then use built-in string class like Nawaz suggested. If you somehow restricted to raw pointers then allocate buffer outside Notation and pass it as destanation parameter like in sprintf or strcat .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM