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
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.
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
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.
> 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.
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
chardst[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
chardst[4];
2
strncpy(dst,"123456",sizeof(dst));
3
dst[sizeof(dst)-1]='\0';
4
5
6
chardst[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.
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!!!
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.
>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...
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
chardst[4];
2
strncpy(dst,"123456",sizeof(dst));
oder
1
chardst[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
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