Summary
Welcome to SO. The main issue is that you're returning the address of a variable that has gone out of scope by the time you try to use it.
Detail
When functions are invoked, local variables are pushed onto a stack (not the data structure!). Here, your local nstr
array variable is pushed and is said to be defined within the function's scope.
However, when functions return, local variables are destroyed along with the stack on which they were placed. This means that your nstr
variable, has already gone out of scope by the time your function has returned.
This causes your caller, main
in this case, to end up with an invalid reference to memory that is no longer in use by the program, which can trigger all sorts of bugs and crashes.
Instead, you should pass a 3rd argument to your function so that it serves as the place where the new concatenated string will go. I don't think making the variable static
here is necessary or a good idea. There's no need to keep something in memory when it shouldn't be.
Updated Code
Based on this, your code should look more like this
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void strcpy2 (char str1[], char str2[], char str3[])
{
// ...
}
int main(void)
{
char str1[10] = "Hello";
char str2[10] = ",friends";
char str3[20];
strcpy2(str1, str2, str3);
puts(str3);
return 0;
}
You should be able to take it from here.
Update - Why You Should Not Use static
Here
Many have recommended using the static
keyword here. I advice against this for the following reasons. Using static
for your local variable causes your function to be:
- Not Thread-Safe:
static
variables are shared variables;
- Not Reusable: function breaks trying to use strings longer than your toy example with a cap of
19+1
chars including null
and defeats the purpose of having a function in the first place;
- Not Memory Efficient: the static variable will remain in memory with a string that no longer needs to be used until your program exits
You'd have a better-quality function if you pass the 3rd argument as a destination that already has enough space to contain the originals to be concatenated.
You could return a pointer that has been malloc
'ed, but note that this is a bit more dangerous and will require more care from everyone using your function. For example, it must be unambiguously clear to every client that it's now their responsibility to free
the memory returned by your function. This can be more error-prone because the malloc
s are not immediately visible to those using it. (Forgot to free
your function's internal/invisible malloc
? Whoops! Hello memory leak!).
Using the 3rd param should be safer in general.
You should really take the time to understand the side-effects and consequences that follow from decisions like these.