Result of calling strcpy is different than expected
Asked Answered
K

3

5
#include <stdio.h>
#include <string.h>

int main()
{
   char src[]="123456";
   strcpy(src, &src[1]);
   printf("Final copied string : %s\n", src);
}

When I use the Visual Studio 6 Compiler it gives me the expected answer "23456".

How come this program prints "23556" when compiled with gcc 4.7.2?

Kayne answered 18/12, 2014 at 12:32 Comment(7)
undefined behaviour, use memmov() insteadTriphibious
how did you come with the fact that it where an overlap ? &Src[1]="23456" right !?! so where is the overlap ?Kayne
@PeterMiehle Yes, memmov plus an extra e.Hammock
src decays to a pointer to the first element of the array src. &src[1] is a pointer to the second element of the array. As the source-string is not of length 0, they obviously overlap.Benavides
this means I have to copy from another string "char dest[]="123456";" and do "strcpy(src, &dest[1]);"Kayne
src = source = from, dst = destination = toTriphibious
I'm asking my self after reading your question again: What is the "expected answer" for undefined behavior? How you can expect even any answer?Scourings
B
13

strcpy(src, &src[1]); is undefined behavior:

C11 §7.24.2.3 The strcpy function

The strcpy function copies the string pointed to by s2 (including the terminating null character) into the array pointed to by s1. If copying takes place between objects that overlap, the behavior is undefined.

By the way, memcpy is similar (but not memmove). See C FAQ: What's the difference between memcpy and memmove.

Beerbohm answered 18/12, 2014 at 12:35 Comment(7)
Hmm... seems to be similar to the memcpy vs memmove issue.Blimp
Where do you find these information's? And how do you find them so quickly? OR have you written your own book :D?Ajit
So this means that the VS compiler is srtonguer for the undefined behaviour or does the coder had a undefined reflexion to write such ligne ?Kayne
@Ajit I have a copy of the C standard draft nearby, if that's what you are asking :). See Where do I find the current C or C++ standard documents?.Beerbohm
@Rizier123: On my system, it is described in the glibc manpages (man 3 strcpy): The strings may not overlap.Waggish
@Blood-HaZaRd: It's undefined behaviour, the implementation can do whatever it pleases.Waggish
Even the 1988 K&R (ANSI) C has this in the first paragraph of Appendix B3 regarding string functions. Any proper C book documents this.Weathercock
S
3

From ISO/IEC 9899:TC3 (c99)

7.21.2.3 The strcpy function

Synopsis

1

#include <string.h>

char *strncpy(char * restrict s1, const char * restrict s2, size_t n);

Description

2 The strcpy function copies the string pointed to by s2 (including the terminating null character) into the array pointed to by s1. If copying takes place between objects that overlap, the behavior is undefined.

So what you are doing is simply undefined behaving ;)

You can also see the ANNEX J.2

Stating cases of undefined behavior with a note how to prevent:

The behavior is undefined in the following circumstances:

[...]

—An attempt is made to copy an object to an overlapping object by use of a library function, other than as explicitly allowed (e.g., memmove) (clause 7).

Scourings answered 18/12, 2014 at 13:13 Comment(0)
L
2

This is undefined behaviour. Use the memmove function instead. memmove is designed to allow overlapping of source and destination buffers.

memmove(src, &src[1], strlen(&src[1]) + 1) ;  // + 1 for copying the terminating zero
Lumpkin answered 18/12, 2014 at 12:36 Comment(3)
Yes the memory overlaps.Unorganized
Instead of the awkward looking &src[1], you can use src+1 for clarity.Fastback
@Fastback you are right, but I left it the same as in the original question on purpose.Lumpkin

© 2022 - 2024 — McMap. All rights reserved.