First of all, the destination str2
is shorter than string length str1
therefore this is an undefined behaviour.
But to understand why this happens, consider the following.
When I print out the memory addresses of the string, before any modification of your code in my system it is like this.
printf("str1: %p (%d) \nstr2: %p (%d)\n", str1, strlen (str1), str2, strlen (str2));
str1: 0x7ffd394e85d0 (19)
str2: 0x7ffd394e85c2 (13)
str1: wwwww
str2: stackoverflowwwwwww
str3:successful
str4:asdfgh
Note the address of str1
and str2
. str2
starts first (lower address) and 0x7ffd394e85d0 - 0x7ffd394e85c2 = e
, which is 13 in decimal, the exact length of the string.
Therefore the initial layout is
Initial layout
0x7ffd394e85c2 0x7ffd394e85d0
str2 str1
| |
| |
V V
s t a c k o v e r f l o w \0 s t a c k o v e r f l o w w w w w w w \0
When the string is being copied from str1
to str2
, strcpy
will align and copy strings as follows. Here the end of str2
buffer gets violated.
When being copied
0x7ffd394e85c2 0x7ffd394e85d0
str2 str1
| |
| |
V V
s t a c k o v e r f l o w \0 s t a c k o v e r f l o w w w w w w w \0
s t a c k o v e r f l o w w w w w w w \0
After copy the state is as follows
After copy
0x7ffd394e85c2 0x7ffd394e85d0
str2 str1
| |
| |
V V
s t a c k o v e r f l o w w w w w w w \0 v e r f l o w w w w w w w \0
Now str1
points to the beginning of the buffer starting with a 'w' and it has five consecutive 'w's until it reaches '\0'. Therefore the C string pointed by str1
now is "wwwww", as you see in your output.
Note that this is for my system where I get five consecutive 'w's. In other systems, the compiler may generate code which has a few blank bytes between the end of str2
and the beginning of str1
, therefore they can have a varying number of 'w's. Also, note that, as this is an undefined behaviour, and the storage layout of the two strings are not defined, the output can be anything.