2

I need to pushback/ append another couple of strings with a given trailing pattern to an existing char array in C. To achieve that, i'm willing to use 'sprintf' as follows.

#include <stdio.h>
#include<string.h>
int main()
{
    char my_str[1024]; // fixed length checked
    char *s1 = "abcd", *s2 = "pqrs";

    sprintf(my_str, "Hello World"); // begin part added
    sprintf(my_str, "%s , push back '%s' and '%s'.", my_str, s1, s2); // adding more to end of "my_str" (with given trailling format)
    /* here we always use 'my_str' as the first for the string format in sprintf - format starts with it */
    return 0;
}

I receive "memory overlapping" warning when i follow this method. is it be a serious issue? (like a memory leak, wrong output, etc.)

7
  • One option is to use strcat instead. Commented Jan 2, 2020 at 6:04
  • 2
    You can't use the same string as both input and output in sprintf(). Commented Jan 2, 2020 at 6:05
  • 2
    Also, note that C and C++ are different languages and only the relevant tag should be used. Quite often the best answer is different depending on whether it is C or C++. Commented Jan 2, 2020 at 6:05
  • 3
    @MawgsaysreinstateMonica String literals get a trailing null automatically, you don't need to put it explicitly. Commented Jan 2, 2020 at 6:07
  • 3
    C11 Standard - 7.21.6.6 The sprintf function "... If copying takes place between objects that overlap, the behavior is undefined." Commented Jan 2, 2020 at 6:14

2 Answers 2

7

You're not allowed to use the same string for input and output when calling sprintf()

So, replace this:

sprintf(my_str, "%s , push back '%s' and '%s'.", my_str, s1, s2);

with this:

sprintf(my_str + strlen(my_str), " , push back '%s' and '%s'.", s1, s2);
Sign up to request clarification or add additional context in comments.

3 Comments

my point is, when the format string is starting with '%s' (eg : "%s<anything>"), it seems to be ok to add the same string for input and output. (because, after i adding "printf("%s", my_str);" i receive the correct output "Hello World , push back 'abcd' and 'pqrs'." in 'onlinegdb.com/online_c_compiler')
@yasaramalshan — the trouble with undefined behaviour is that it can seem to work as you expected (even if your expectations are unfounded), but it can work differently at any time, and there's nothing you can do except fix your code because you broke the constraints on how you can safely use sprintf(). Don't rely on undefined behaviour that happens to work at the moment on your machine; it may not work ever again.
The solution shown here eliminates the overlap and should be fine. However, I would suggest using snprintf and possibly keeping track of the string length as you add to it (snprintf returns the number of characters printed) so that you can just use something like (buffer_size - total_printed) for the size argument and avoid a buffer overrun. You can also use that value to avoid unnecessarily calling strlen().
2

The warning is because you're not allowed to use the same string for both the output of sprintf() and one of the input arguments. The specification says:

If copying takes place between objects that overlap, the behavior is undefined.

Use a new string for the output.

#include <stdio.h>
#include<string.h>
int main()
{
    char my_str[1024], my_str2[1024]; // fixed length checked
    char *s1 = "abcd", *s2 = "pqrs";

    sprintf(my_str, "Hello World"); // begin part added
    sprintf(my_str2, "%s , push back '%s' and '%s'.", my_str, s1, s2); // adding more to end of "my_str" (with given trailling format)
    return 0;
}

2 Comments

my point is, when the format string is starting with '%s' (eg : "%s<anything>"), it seems to be ok to add the same string for input and output. (because, after i adding "printf("%s", my_str);" i receive the correct output "Hello World , push back 'abcd' and 'pqrs'." in 'onlinegdb.com/online_c_compiler')
I've added the quote from the specification that says it's not allowed. Just because it worked when you tried it, it doesn't mean it's generally OK.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.