I got this homework to decide what the following code will do (on paper, without testing on computer).
char s1[]="Short Message Service", *s2, *s3;
s2=strchr(s1,'M');
s3=strchr(s2,'S');
strncpy(s1+1,s2,1);
strcpy(s1+2,s3);
When I wanted to check if I did it right, I ran it on computer and got this result:
s1 = SMservice
s2 = ice
s3 = Service
I thought that s2
will be "Message Service"
but it changes to "ice"
. Apparently it changes after strcpy(s1+2,s3)
is called; can somebody explain why and how that function affects s2
?
The answer is "undefined behaviour" — anything can happen. The arguments to strcpy()
and strncpy()
must not overlap. — yet here, the arguments to strcpy()
do overlap.
C11 §7.24.2.3 The strcpy
function ¶2:
The
strcpy
function copies the string pointed to bys2
(including the terminating null character) into the array pointed to bys1
. If copying takes place between objects that overlap, the behavior is undefined.
§7.24.2.4 The strncpy
function ¶2
The
strncpy
function copies not more thann
characters (characters that follow a null character are not copied) from the array pointed to bys2
to the array pointed to bys1
.308) If copying takes place between objects that overlap, the behavior is undefined.308) Thus, if there is no null character in the first
n
characters of the array pointed to bys2
, the result will not be null-terminated.
That means there is no reliable answer that can be given. You might decide that you'd then describe what would happen if the copy operations copy from the start of the source over the destination, which is what your instructor likely expects. But that is not guaranteed behaviour.
Given the following code and the left-to-right copying assumption:
char s1[] = "Short Message Service";
char *s2 = strchr(s1, 'M');
char *s3 = strrchr(s2, 'S');
strncpy(s1+1, s2, 1);
strcpy(s1+2, s3);
We can deduce that s2
points to &s1[6]
and s3
points to &s1[14]
(and this is mandatory). The values in s1
at various stages are:
s1 = "Short Message Service" -- initial text
s1 = "SMort Message Service" -- after strncpy
s1 = "SMService" -- after strcpy (but this assumes UB works as expected)
So the string starting at s2
now contains ice
, as you found.
However, it must be re-emphasized, this is not required behaviour.