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

20,242

Solution 1

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

Solution 2

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.

Solution 3

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.

Share:
20,242
Wartin
Author by

Wartin

Updated on September 08, 2020

Comments

  • Wartin
    Wartin over 3 years

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