Wenn man byteweise von hinten nach vorne kopiert, dann funktioniert das mit so trivialen strcpy(3)-Implementierungen wie die von der du den Code gepostet hast. Implementierungen in optimierten C-Libraries kopieren vermutlich nicht byteweise sondern versuchen das ``besser'' zu machen, was in so Faellen dann wohl nicht mehr geht.
Deine Implementierung funktioniert in anderen Faellen auch nicht, z.B. strcpy(s+8, s) ... einen genuegend grossen Buffer vorausgesetzt:
Das Nach-vorne-Ruecken ist ein Sonderfall, den eine Implementierung dieser (naheliegenden trivialen) Art auch bei Ueberlappung beherrscht. Andere Implementierungen oder andere ueberlappende Faelle funktionieren nicht. Darum sagt meine Manpage:
Manpage zu strcpy(3) hat geschrieben:
For all of strcpy(), strncpy(), stpcpy(), and stpncpy(), the result is
undefined if src and dst overlap.
Was rauskommt ist undefiniert: Es kann klappen oder auch nicht. Das haengt von der konkreten Situation und von der strcpy-Implementierung ab.
Edit:
Dein char_shift() ist doch eine tolle Hilfsfunktion. Ich wuerde nur noch etwas die Benennung verbessern: `str' statt `char', weil sie auf einem String arbeitet und nicht mit einem einzelnen Char ... also vielleicht `strdelpart'. Und statt `offset' besser `nchars' -- so viele Zeichen willst du ja aus dem String loeschen. Den ersten Parameter wuerde ich vielleicht `from' nennen.
Benennungen sollte man aus Aufrufersicht machen. Deine Funktion entfernt aus dem String, den du im ersten Argument uebergibst, die ersten n Zeichen, was im zweiten Argument angegeben ist.