mikrocontroller.net

Forum: Compiler & IDEs Unterschied zwischen strcpy und memcpy ?


Autor: Karlheinz Druschel (kdruschel)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>strcpy( dst, src );

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

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: A. F. (artur-f) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
 memcpy (dest,src,strlen(src)); 
ist so ziemlich das Gleiche wie
strcpy (dest,src); 

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
   char dst[4];
   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.
   char dst[4];
   strncpy( dst, "123456", sizeof(dst) );
   dst[sizeof(dst)-1] = '\0';


   char dst[4] = 0;
   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.

Autor: Ulrich (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!!!

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
   char dst[4];
   strncpy( dst, "123456", sizeof(dst) );

oder
   char dst[4];
   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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.