Forum: Mikrocontroller und Digitale Elektronik Mid(), Left()... in C für AVR


von Christoph (Gast)


Lesenswert?

Sorry Leut,

aber warscheinlich seh ich schon den Wald vor lauter Bäumen nicht. Ich 
arbeite mit avr-libc und procyon Bibs und bin auf der Suche nach der 
"mid-Funktion" (also eben einen Teil aus einem String herausschneiden). 
Das wird es doch bestimmt schon geben, oder? Könnte mir mal bitte jemand 
den Funktionsnamen verraten.

Danke

von Philipp S. (philipp)


Lesenswert?

Gibt's in der Form in C nicht. Es kommt darauf an, was damit passieren 
soll. Wenn Du den Originalstring nicht mehr brauchst:

char String[] = "Die Mitte rausschneiden";
// Neuer String soll "Mitte" lauten!
String[9] = 0;   // Leerzeichen hinter "Mitte" mit Stringende 
überschreiben
char * Mittenstring = String + 4;   // Zeigt auf das M
printf(Mittenstring);   // gibt "Mitte" aus.



Wenn Du ihn noch brauchst, kopierst Du stattdessen mit strncpy:

strncpy(Zielstring, String + 4, 5);

D.h. also die Zeichenkette, die vier Zeichen hinter dem Stringanfang 
beginnt (also beim M) fünf Zeichen lang kopieren. Der String wird dann 
automatisch mit einer Null abgeschlossen.

von Christoph (Gast)


Lesenswert?

Hallo Philipp,

vielen Dank für die Antwort. Mit letzterem kann ich eher was anfangen.

Gruß Christoph

von Peter D. (peda)


Lesenswert?

Kannst Du mal beschreiben, was eine mid-Funktion macht ?

In C wird gerne mit Pointern gearbeitet.
Wenn man also aus einem Text den Rest ab dem 5. Zeichen ausgeben will, 
schreibt man einfach

printf("%s", text+5);

Nur wenn man was verändern und das Original behalten will, muß man 
wirklich kopieren, z.B. mit strncpy().


Peter

von A.K. (Gast)


Lesenswert?

"Der String wird dann automatisch mit einer Null abgeschlossen."

Dieses naheliegende Missverständnis bei strncpy() dürfte für einen Teil 
der berüchtigten buffer overflows verantwortlich sein.

Nein. So ist es eben nicht. Doku zu strncpy lesen.

von Philipp S. (philipp)


Lesenswert?

Wow, nicht schlecht, das hatte ich wirklich vergessen. Bei strcpy wird 
also die Null mitkopiert, bei strncpy aber nur, wenn auch das Ende des 
Ursprungsstrings erreicht wird. Der einzige Unterschied zu memcpy ist 
also, daß bei letzterem hinter dem Ursprungsstringende der Rest mit 
Nullen aufgefüllt wird (was in 99% der Fälle niemanden interessiert). 
Wer hat sich das so ausgedacht?

Jetzt muß ich wirklich nochmal überprüfen, ob alle Benutzungen dadurch 
gesichert sind, daß von der Allokation noch die Nullen übrig sind. Also 
vielen Dank!

von Niels H. (monarch35)


Lesenswert?

Bitte auch nicht vergessen:
String-Oprationen müssen im internen RAM abgearbeitet werden. Der Platz 
dafür ist auf einigen u-Plattformen sehr kostbar.

von Karl heinz B. (kbucheg)


Lesenswert?

> Der einzige Unterschied zu memcpy ist
> also, daß bei letzterem hinter dem Ursprungsstringende der Rest
> mit Nullen aufgefüllt wird (was in 99% der Fälle niemanden
> interessiert).

Äh, nein, das kann man so nicht sagen.

memcpy interessiert sich überhaupt nicht für den Inhalt
des Speichers. memcpy() kopiert einfach nur Speicherbereiche,
was auch immer da drinn enthalten ist. Da wird nichts
aufgefüllt. Wenn im Quellstring zufällig nach dem ersten '\0'
Byte noch weitere '\0' Bytes kommen, dann werden die selbst-
verständlich mitkopiert. Das liegt aber nicht daran, dass
das '\0' Bytes sind, sondern einfach daran dass memcpy()
Speicherbereiche ohne Ansehen des Inhalts kopiert.

mem...()  Funktionen: Arbeiten direkt auf dem Speicher
                      ohne Ansehen des Inhalts.
                      memcmp() als Vergleichsfunktion ist
                      natürlich die Ausnahme.

str...() Funktionen:  Arbeiten in einem gewissen Sinne auch
                      direkt auf dem Speicher. Zusätzlich
                      wird aber immer berücksichtigt, dass ein
                      '\0' Byte das Ende des zu bearbeitenden
                      Bereiches anzeigt.

Daher: Bei mem...() Funktionen muss immer die Länge des zu
bearbeitenden Speicherbereiches angegeben werden. Die mem...()
Funktionen treffen keinerlei Annahmen darüber, was sich im
Speicher an den angegebenen Stellen verbirgt. Für die mem...()
Funktionen ist das einfach nur eine Abfolge an Bytes.

Die str...() Funktionen in der 'klassischen Variante', bekommen
keine Längeninformation mit, sondern leiten diese vom Auftreten
des '\0' Bytes ab. Es gibt also ein spezielles Byte, dass die
Arbeit der str...() Funktion leitet. Von dieser einen Ausnahme
abgesehen kümmern sich auch die str...() Funktionen nicht weiter
um den Byte-Inhalt der bearbeiteten Speicherfelder.

Da sich aber die 'klassischen str...() Funktionen' als relativ
gefährlich herausgestellt haben, hat es im Lauf der Zeit eine
Erweiterung um die 'n' Funktionen gegeben (strncpy, strncmp),
bei denen zusätzlich noch Längeninformation mitgegeben werden
muss. Diese Funktionen benutzten dann zusätzlich zum '\0' Byte
noch diese Längeninformation um sicherzustellen, dass Speicher-
bereiche nicht überlaufen werden. Es gilt: Ein String ist dann
zu Ende, wenn entweder der übergebene Längenparameter aufgebraucht
ist oder ein '\0' Zeichen angetroffen wurde. Je nachdem was zuerst
auftritt. Bei den 'n' Funktionen kann es auch passieren, dass bei
einem Ergebnisstring kein '\0' auftaucht, weil die Längenangabe
eines Zieles nicht gross genug war um diesen String komplett
aufzunehmen.


von A.K. (Gast)


Lesenswert?

Die Erfahrung zeigt, dass die Funktionen strncpy() und vor allem 
strncat() mehr Gefahren als Nutzen darstellen. Beiden fehlt gern die 
Null am Ende, und strncat() stellt keineswegs sicher, dass der 
Zielstring nicht überläuft, das "n" bezieht sich ja nicht auf dem Platz 
im Zielpuffer, sondern auf die Länge vom Quellstring.

Empfehlung: Wenn die string-Library nicht sowieso schon bessere 
Versionen davon zur Verfügung stellt: Finger weg davon und eigene 
sichere Versionen basteln.

von Philipp S. (philipp)


Lesenswert?

>> Der einzige Unterschied zu memcpy ist
>> also, daß bei letzterem hinter dem Ursprungsstringende der Rest
>> mit Nullen aufgefüllt wird (was in 99% der Fälle niemanden
>> interessiert).

> Äh, nein, das kann man so nicht sagen.

Jetzt mal abgesehen davon, daß ich den Satz noch umformuliert hatte, 
wodurch »letzterem« plötzlich keinen Bezug mehr hatte (sorry!), kann man 
das m.E. auch nach Deiner Erklärung immer noch so sagen:

* Kommt keine Null innerhalb der angegebenen Länge, verhalten sie
  sich gleich
* Kommt eine Null, wird bei strncpy hinter dem Ursprungsstringende
  der Rest mit Nullen aufgefüllt (wofür sich wie gesagt normalerweise
  niemand für interessiert, wenn das Ergebnis als String genutzt wird)

Und so bleibt meine Frage: warum hat man das so gemacht? Das verstehe 
ich wirklich nicht.

von Karl heinz Buchegger (Gast)


Lesenswert?

Keine Ahnung.
Ich kann mir auch keinen wirklich guten Grund ausdenken,
warum ich das machen würde.

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.