skip to Main Content

I’m writing c code using wsl with gcc compiler.And I tried to delete a space in front of a c-string with strcpy and got a strange result.
The string I tried to modify is s = {‘ ‘,’e’,’h’,’c’,’o’ ,”};And I use a pointer temp to point at the "e"in the string and then I use strcpy(s,temp) to delete the space.BUT the result I get is ecoo,not echo.

#include  <stdio.h>
#include  <unistd.h>
#include  <string.h>
int main(){
    char a[256];
    a[0] = ' ';
    a[1] = 'e';
    a[2] = 'h';
    a[3] = 'c';
    a[4]  = 'o';
    a[5] = '';
    char* temp = a;
    temp ++ ;
    printf("%sn",temp);
    strcpy(a,temp);
    printf("%sn",a);
    
}

I tried to debug in the program and temp is indeed "echo"but the result is ecoo.
The code went as expected in the windows system in visual studio and vscode.
And I also tried different string length and I found out the code went well when the length of the string is 3,7.
enter image description here

3

Answers


  1. Your code is invalid. From https://en.cppreference.com/w/c/string/byte/strcpy :

    The behavior is undefined if the strings overlap.

    temp is equal to a + 1 – they overlap. strcpy(a, a + 1) is not valid.

    Login or Signup to reply.
  2. The C standard says that using strcpy() to copy strings that overlap is undefined behaviour.

    When I compile your code (Clang on macOS, intel 64) I don’t see the same result as you, I see

    ehco
    zsh: illegal hardware instruction  ./a.out
    

    which suggests it is using some built in function that detects the overlap, probably because the strings are very short.

    What you see is an artefact of the way strcpy is implemented on your environment. At a guess, I would say it’s copying from the back and stopping when it thinks it has copied all of temp characters.

    Anyway, do not use strcpy() on arrays/buffers that overlap.

    Login or Signup to reply.
  3. As already mentioned, strcpy assumes that the two parameters don’t overlap. In case they do, you invoke undefined behavior. See for example man strcpy.

    The solution is to use the memmove function instead, which is a specialized function to use for the very situation when you do have two memory areas that overlap. It uses an internal temporary buffer to fix that.

    Therefore replace your strcpy call with memmove(a, temp, strlen(temp)+1);. Since memmove is a general function it knows nothing of strings, therefore we have to add a +1 in the end to tell it to also copy the null terminator (so you get "echo" and not "ehcoo").

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search