Forum: Compiler & IDEs Unterschied zwischen strcpy und memcpy ?


von Karlheinz D. (kdruschel)


Lesenswert?

Hi Leuts,

kann mir mal jemand erklären, worin der Unterschied zwischen "strncpy 
(x, y, 5) und memcpy (y,x,5) liegt ?

Ein Unterschied ist mir ja klar: strncpy kopiert maximal 5 Bytes, wenn 
der Sourcestring an Byte [39 mit 0 terminiert, dann hört er da auf. 
Memcpy kopiert alle 5 Bytes.

Aber das meine ich nicht.
Ich habe folgendes Problem:

uint8_t s1[10], s2[10];

strncpy (s1,"12345");             // geht
strncpy (s1, s2, 15);             // geht nicht, s2=""
memcpy (s2, s1, 15);              // geht, s2="12345";

Ein Vertauschen von Source-, und Targetpointer kann auch nicht sein, 
dann wäre ja s1 mit 0 überschrieben.
Warum geht das strncpy nicht (strcpy geht auch nicht)...

Greets
Karlheinz

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karlheinz Druschel wrote:

> kann mir mal jemand erklären, worin der Unterschied zwischen "strncpy
> (x, y, 5) und memcpy (y,x,5) liegt ?

Dass das eine von y nach x, das andere von x nach y kopiert -- weil du
die Argumente vertauscht hast.  Die Position ist nämlich bei beiden
Funktionen die gleiche.

> strncpy (s1,"12345");             // geht

Ach?  Trotz des fehlenden Parameters?

> strncpy (s1, s2, 15);             // geht nicht, s2=""

Was geht denn nicht?  s2 wird dabei jedenfalls nicht geändert...

> Ein Vertauschen von Source-, und Targetpointer kann auch nicht sein,
> dann wäre ja s1 mit 0 überschrieben.

Genau.  Weil man die Symptome nicht deuten kann, kann's natürlich
daran nicht liegen, dass man die Funktion nicht richtig benutzt...

Ja, du hast die beiden Zeiger vertauscht.  Ein Blick in ein
beliebiges C-Buch hätte dir das sagen können.

von Peter (Gast)


Lesenswert?

Ich denke bei

 strncpy (s1, s2, 15);

ist Source- und Targetpointer vertauscht.

bei
strncpy (s1,"12345");
ist ja auch der erste Parameter das Ziel, warum soll das später anders 
sein.

Mit strcpy kann man keine 0 kopieren, das geht mit memcpy

von Karl H. (kbuchegg)


Lesenswert?

Und als Merkhilfe: die Bedeutung der Parameter ist an eine ganz normale 
Zuweisung angelehnt

   dst = src;

zuerst liest man bei normaler westlicher Leseart von links nach rechts 
das Ziel (dst == destination) dann die Quelle (src == source).

Und genau in dieser Reihenfolge sind auch die Argumente im strcpy / 
memcpy angeordnet

   strcpy( dst, src );


Zum Unterschied:
Alle Funktionen der str...  Familie sind für String Bearbeitung gedacht. 
Sie wissen also um die Sonderbedeutung eines 0-Bytes bescheid.
Wohingegen sich alle Funktionen der mem... Familie auf die reinen Bytes 
stürzen und alle möglichen Bytewerte gleich behandeln - sprich sie sind 
ihnen sch.... egal. Der Programmierer will 15 Bytes kopiert haben, also 
werden auch 15 Bytes kopiert.

Generell sollte man, auch wenn man es manchmal sieht, die mem... 
Funktionen nicht zur Bearbeitung von Strings benutzen. Der str... 
Funktionsname sagt dir nämlich auch nach 2 Jahren beim erneuten Studium 
des Codes, das du es hier mit Strings zu tun hast und nicht einfach nur 
mit irgendwelchen Bytefolgen, die Gott weiss was bedeuten können.

von Matthias L. (Gast)


Lesenswert?

>strcpy( dst, src );

Allerdings haben "normale" Stringfunktionen alle das Problen, dass die 
nicht wissen wieviel Platz noch im Puffer ist.
1
strcpy( dst, src , free );
2
//mit:
3
free = sizeof(dst)-strlen(dst);
wäre sinnvoller. Aber ich glaube, sowas gibt es mittlerweile als 
save_str...

von Peter (Gast)


Lesenswert?

> strcpy( dst, src , free );
> free = sizeof(dst)-strlen(dst);
Das wird leider recht selten gehen, weil ein sizeof nicht mit einem 
char* klar kommt, ausdem ist ein zusätzlicher strlen zu langsam. (String 
muss 2mal geparst werden.

es gibt aber wie schon oben gesagt strNcpy da kann man die länge 
mitgeben.

von A. F. (artur-f) Benutzerseite


Lesenswert?

1
 memcpy (dest,src,strlen(src));
ist so ziemlich das Gleiche wie
1
strcpy (dest,src);

kbuchegg hats schon richtig gesagt, bei Strings sollte man memcpy nicht 
benutzen.

von Karl H. (kbuchegg)


Lesenswert?

Peter wrote:
>> strcpy( dst, src , free );
>> free = sizeof(dst)-strlen(dst);
> Das wird leider recht selten gehen, weil ein sizeof nicht mit einem
> char* klar kommt, ausdem ist ein zusätzlicher strlen zu langsam. (String
> muss 2mal geparst werden.
>
> es gibt aber wie schon oben gesagt strNcpy da kann man die länge
> mitgeben.

Wobei man auch mal sagen muss, dass nur die alleinige Benutzung von 
strncpy auch nicht Anlass zu Jubelschreien geben sollte.

Denn: Wenn der Platz in dst (ich geh mal davon aus, dass das n die 
tatsächliche Größe von dst wiederspiegelt und nicht aus irgendwelchen 
anderen Gründen künstlich kleiner gehalten wird) aufgebraucht ist, dann 
macht strncpy kein abschliessendes 0-Byte an den Zielstring!

Mit
1
   char dst[4];
2
   strncpy( dst, "123456", sizeof(dst) );

ist zwar die unmittelbare Gefahr beim strncpy gebannt, allerdings hat 
man dann in dst keinen gültigen String mehr und wird spätestens bei den 
nächsten Stringmanipulationen auf die Nase fallen.
1
   char dst[4];
2
   strncpy( dst, "123456", sizeof(dst) );
3
   dst[sizeof(dst)-1] = '\0';
4
5
6
   char dst[4] = 0;
7
   strncpy( dst, "123456", sizeof(dst)-1 );

Beide Varianten sind schon besser. Zumindest wird der String wieder 
korrekt terminiert. Ob allerdings nachfolgende Programmteile, die sich 
unter Umständen darauf verlassen, dass der String auch wirklich komplett 
umkopiert wurde, damit klarkommen dass dem nicht so ist, steht wiederrum 
auf einem ganz anderen Blatt.

von Ulrich (Gast)


Lesenswert?

memcpy (dest,src,strlen(src));

so wird das nichts. Wenn schon so ein murks dann so:
 memcpy (dest,src,strlen(src)+1);
sonst ist das char-array in dest eventuell nicht mehr \0 terminiert!!!

von Peter (Gast)


Lesenswert?

Ich sehe mehr das Problem mit dem

sizeof(dst) das geht wirklich bloss wenn ein array übergeben wurde. Aber 
sogut wie jede funktion bekommt ein char* rein. Damit kann sizeof() 
nicht sinnvollen anfangen.

von Matthias L. (Gast)


Lesenswert?

>Aber sogut wie jede funktion bekommt ein char* rein. Damit kann sizeof()
>nicht sinnvollen anfangen.

Du hast es erfasst!
Deshalb ja der Einwand, das "jede funktion" zusätzlich zum char* noch 
das die Länge des Puffers braucht, auf das char* zeigt!

sizeof() ist ja eine zur Compilezeit bekannte Komstante...

von Karl H. (kbuchegg)


Lesenswert?

Peter wrote:
> Ich sehe mehr das Problem mit dem
>
> sizeof(dst)


Ja, klar.
Das war ja auch ein konstruiertes Beispiel. Ist doch im Grunde egal
ob da jetzt
1
   char dst[4];
2
   strncpy( dst, "123456", sizeof(dst) );

oder
1
   char dst[4];
2
   strncpy( dst, "123456", 4 );

steht. (Wie also strncpy zu seiner Längenangabe kommt)

Der springende Punkt ist: Selbst dann ist das immer noch nur die halbe 
Miete und man ist global gesehen noch nicht auf der sicheren Seite

von Karl H. (kbuchegg)


Lesenswert?

Karl heinz Buchegger wrote:

> Der springende Punkt ist: Selbst dann ist das immer noch nur die halbe
> Miete und man ist global gesehen noch nicht auf der sicheren Seite

Worauf ich hinaus will:

Es ist nicht so, dass man in einem Programm nur alle strcpy durch 
strncpy mit korrekter Längenangabe ersetzen muss, und schon ist alles 
Friede, Freude, Eierkuchen.

Nur leider sieht man oft Programme, bei denen sich einem der Eindruck 
aufdrängt, der Programmierer ist genau dieser Meinung

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.