Größe von String herausfinden

Gast #3626706
Lesenswert?

Hallo,

ich habe mir eine Funktion geschrieben, die einen String übergeben 
bekommt. In der weiteren Berechnung benötige ich nun aber auch die Länge 
des Strings. Ist es möglich diese mit einem Befehl zu ermitteln oder 
muss ich sie auch übergeben?
1
void function(char array[]) {
2
...
3
}
4

5
int main(void) {
6
   function("Hallo");
7
   return EXIT_SUCCESS;
8
}
#3626712
Lesenswert?

Für welche Programmiersprache willst du das denn wissen?

Ich gehe mal aus daß es sich um C handelt. Soweit ich mich beim K&R 
erinnere ist das eine der ersten Funktionen die überhaupt behandelt 
werden.

Wenn du das also nicht weisst, dann hast du noch nicht mal die ersten 
beiden Kapitel deines C Buchs durchgearbeitet.
Wenn du mit so wenig Grundlagen versuchst zu programmieren kann das nur 
mit Schiffbruch enden.

Also nimm oder besorge dir ein C Buch. Arbeite das durch, dann wird das 
was.
#3626773
Lesenswert?

Einem C-Anfänger sei ohnehin angeraten sich mit den Fussangeln zu 
beschäftigen die nullterminierte Strings mit sich bringen, auf dass sein 
Produkt nicht irgendwann zum Gegenstand einer Sicherheitswarnmeldung 
wird.

Schau ob deine Implementation strnlen() anbietet, aber sei gleichzeitig 
behutsam mit willkürlichen Längenbeschränkungen, die sollten 
dokumentiert werden wenn mit Strings gearbeitet wird die im Zusammenhang 
mit Dateien oder Netzwerkverkehr stehen.
Eine einfache strlen()-Implementation kann man mit unbrauchbaren Daten 
zB vom Netz oder aus einer manipulierten/fehlerhaften Datei schnell dazu 
bewegen sehr hohen Ressourcenverbrauch und/oder einen Programmabsturz 
herbeizuführen.
Gast #3626795
Lesenswert?

Andy D. schrieb:
> Einem C-Anfänger sei ohnehin angeraten sich mit den Fussangeln zu
> beschäftigen die nullterminierte Strings mit sich bringen, auf dass sein
> Produkt nicht irgendwann zum Gegenstand einer Sicherheitswarnmeldung
> wird.
>
> Schau ob deine Implementation strnlen() anbietet, aber sei gleichzeitig
> behutsam mit willkürlichen Längenbeschränkungen, die sollten
> dokumentiert werden wenn mit Strings gearbeitet wird die im Zusammenhang
> mit Dateien oder Netzwerkverkehr stehen.
> Eine einfache strlen()-Implementation kann man mit unbrauchbaren Daten
> zB vom Netz oder aus einer manipulierten/fehlerhaften Datei schnell dazu
> bewegen sehr hohen Ressourcenverbrauch und/oder einen Programmabsturz
> herbeizuführen.

Immer diese Anspielungen ;-) http://xkcd.com/1354/
Gast #3626910
Lesenswert?

Ein Nullterminierter C-Stringist etwas vom Duemmlichsten, das man sich 
vorstellen kann.Die Laenge braucht man ja eh sowieso. Weshalb sollte man 
sich mit Code Zeit verplempern, wen mn sich die Lenge auch merken kann. 
Sinnvollerweise verwendet man das Nullte Byte des Strings um die Laenge 
festzuhalten.
Gast #3627075
Lesenswert?

Warum nicht einfach konsequent immer die String-Länge als extra 
Parameter übergeben und sich somit den Zeit-Verlust durch strlen und die 
Sicherheitslücken durch Buffer-Overflows sparen? Oder, natürlich, C++ 
verwenden, welches eine String-Klasse hat:
1
void function(std::string myStr) {
2
  std::cout << "Mein string ist " << myStr.size () << " Zeichen lang.\n";
3
}
4

5
int main() {
6
   function("Hallo");
7
   return EXIT_SUCCESS;
8
}
Gast #3627085
Lesenswert?

Jaja, dem schönen alten PASCAL nachflennen.
Ich bin gerührt.

Bei C muss man sich nun mal Gedanken über den Speicherverbrauch
machen. Besonders bei µCs mit knappen Resourcen ist das doch
sowieso erforderlich!
#3627116
Lesenswert?

Hallo Chris,

Chris schrieb:
> ich habe mir eine Funktion geschrieben, die einen String übergeben
> bekommt. In der weiteren Berechnung benötige ich nun aber auch die Länge
> des Strings. Ist es möglich diese mit einem Befehl zu ermitteln oder
> muss ich sie auch übergeben?
>
>
1
> void function(char array[]) {
2
> ...
3
>

Damit Du zur Abwechslung auch mal eine Antwort bekommst, mit der Du als 
Anfänger etwas anfangen kannst:
Die Programmiersprache C (oder C++, die in dem Fall eine echte Obermenge 
ist) übergibt an dieser Stelle faktisch nur einen Zeiger auf ein Array, 
das Elemente vom Typ Char enthält. Du kannst also die Länge des Strings 
nur dann erkennen, wenn sie aus dem String selber erkennbar ist, z. B. 
wenn der String nullterminiert ist.

Wenn Du z. B. einen Aufruf machst
1
function("ABC");
, dann übergibt der Compiler faktisch
1
function(['A', 'B', 'C', '\0']);
.

In diesem Fall kannst Du strlen() benutzen und es liefert 3 (das 
versteckte Nullbyte wird nicht mitgezählt). Wenn Du aber an der Stelle 
nur z. B. ein Array ['A', 'B', 'C'] übergibst, dann hast Du keine Chance 
herauszufinden, wie lang das Array tatsächlich ist und brauchst einen 
zusätzlichen Parameter für die Länge.

Falls Du C++ benutzt, so gibt es Arrayklassen, z. B. in der STL, wo die 
Länge implizit übergeben wird.

Tschüß, Matthias
Gast #3627169
Lesenswert?

>Boahh schrieb:
>> Sinnvollerweise verwendet man das Nullte Byte des Strings um die Laenge
>> festzuhalten.
>
>Bist du von BASIC Strings mit maximal 255 Zeichen gewohnt?

Auf einem Controller ist ein String von 255 byte bereits jenseits von 
vorstellbar. Was soll ich damit? Ein grosser LCD hat vielleicht 4x20, 
heisst, ich bin mit 20 Byte zufrieden.

Nein, Strings zaehle ich nie, denn ich weiss ja die Laenge.
#3627277
Lesenswert?

Matthias H. schrieb:
> Damit Du zur Abwechslung auch mal eine Antwort bekommst, mit der Du als
> Anfänger etwas anfangen kannst:

Das ist unfair, denn den wirklich sinnvollen Vorschlag bekam er ziemlich 
zu Anfang:

Udo Schmitt schrieb:
> Also nimm oder besorge dir ein C Buch. Arbeite das durch, dann wird das
> was.

Zumal C++ hier auch nicht hilfreich ist, und das ebenfalls nur verwirrt:
Matthias H. schrieb:
> , dann übergibt der Compiler faktischfunction(['A', 'B', 'C', '\0']);

Wie du selber weisst, wird eben bei einem String in C gerade nicht ein 
Feld übergeben, sondern nur die Anfangsadresse.



Anstatt hier anhand von Gerüchten C zu lernen, wäre der gute Mann 
wirklich mit einem guten Buch besser bedient - was er sich selber hätte 
denken können.
Gast #3627333
Lesenswert?

Andy D. schrieb:
> Schau ob deine Implementation strnlen() anbietet, aber sei gleichzeitig
> behutsam mit willkürlichen Längenbeschränkungen, die sollten
> dokumentiert werden wenn mit Strings gearbeitet wird die im Zusammenhang
> mit Dateien oder Netzwerkverkehr stehen.

> Eine einfache strlen()-Implementation kann man mit unbrauchbaren Daten
> zB vom Netz oder aus einer manipulierten/fehlerhaften Datei schnell dazu
> bewegen sehr hohen Ressourcenverbrauch und/oder einen Programmabsturz
> herbeizuführen.

Also wenn sich jemand ein Netzwerkprotokoll oder Fileformat ausdenkt, in 
dem nullterminierte Strings stehen und diese dann noch direkt ungeprüft 
übernimmt, dann drucke ich dem gerne seinen Code aus und schlag ihm den 
um die Ohren. Da wo das strlen() steht, muß schon lange geklärt sein, 
daß da ein korrekt nullterminierter String steht, sonst kommt so oder so 
Mist raus. strnlen() rettet da dann auch nicht mehr wirklich was.
Gast #3627337
Lesenswert?

Rolf Magnus schrieb:
> Also wenn sich jemand ein Netzwerkprotokoll oder Fileformat ausdenkt, in
> dem nullterminierte Strings stehen und diese dann noch direkt ungeprüft
> übernimmt, dann drucke ich dem gerne seinen Code aus und schlag ihm den
> um die Ohren.

warum? Und wenn dort dann 10GB Daten ankommen und dann erst eine \0 und 
er dafür richtig Speicher anfordert wo soll das das Problem sein?

Was willst du denn Prüfen wenn das Protokoll nullterminierte Strings 
vorsieht?

Man muss nur dafür sorgen, das der Speicher dafür ausreicht und wenn 
nicht das das man sinnvoll abbricht. Das hat aber alles nichts mit 
strlen zu tun.
Gast #3627346
Lesenswert?

Peter II schrieb:
> Rolf Magnus schrieb:
>> Also wenn sich jemand ein Netzwerkprotokoll oder Fileformat ausdenkt, in
>> dem nullterminierte Strings stehen und diese dann noch direkt ungeprüft
>> übernimmt, dann drucke ich dem gerne seinen Code aus und schlag ihm den
>> um die Ohren.
>
> warum? Und wenn dort dann 10GB Daten ankommen und dann erst eine \0 und
> er dafür richtig Speicher anfordert wo soll das das Problem sein?

Und wenn das \0 nicht da steht, lesen seine Stringfunkionen munter nach 
dem Ende der Daten weiter im Speicher rum.

> Was willst du denn Prüfen wenn das Protokoll nullterminierte Strings
> vorsieht?

Daß auch tatsächlich Nullterminierungen da sind.
Gast #3627349
Lesenswert?

Rolf Magnus schrieb:
> Und wenn das \0 nicht da steht, lesen seine Stringfunkionen munter nach
> dem Ende der Daten weiter im Speicher rum.

sie kann ja noch kommen.

> > Was willst du denn Prüfen wenn das Protokoll nullterminierte Strings
> > vorsieht?
> Daß auch tatsächlich Nullterminierungen da sind.

und wo hörst du auf mit lesen, wenn im Protokoll keine MAX Länge 
definiert ist?


    |
Gast #3627355
Lesenswert?

короткое троль schrieb:
>>Boahh schrieb:
>>> Sinnvollerweise verwendet man das Nullte Byte des Strings um die Laenge
>>> festzuhalten.
>>
>>Bist du von BASIC Strings mit maximal 255 Zeichen gewohnt?
>
> Auf einem Controller ist ein String von 255 byte bereits jenseits von
> vorstellbar. Was soll ich damit? Ein grosser LCD hat vielleicht 4x20,
> heisst, ich bin mit 20 Byte zufrieden.
>
> Nein, Strings zaehle ich nie, denn ich weiss ja die Laenge.

Soso.

Tellerand und dahinter ist nicht?
Mein Board hier hat kein LCD und muss trotzdem Strings verarbeiten die 
unter Umständen weit jenseits der 255 Zeichen sind.

Hey, ich brauch allein mehr um nen einzelnen Flash Block zu ändern.

Gibt halt nicht nur AVR und PIC.
Gast #3627361
Lesenswert?

Danke für die ganzen Antworten. Zu meiner Ehrenrettung möchte ich sagen, 
dass ich kein ganz so blutiger Anfänger bin, wie der Frage vermuten 
lässt. Ich habe nur seit Jahren ausschließlich embedded programmiert und 
dadurch seit Ewigkeiten nicht mit Strings gearbeitet. Aber dank eurer 
Antworten kam mir langsam wieder alles...
Meine Funktion bekommt einen String übergeben, der auf einem LCD 
angezeigt wird. Dann gebe ich jedes Zeichen aus, bis der Inhalt 0 ist. 
Den Inhalt gebe ich im Quellcode vor, den Speicher werde ich also nicht 
überlasten. Ich könnte natürlich auch immer die Länge übergeben, aber so 
gefällt es mir besser.
Nochmal danke!

Klaus Wachtler schrieb:
> Unwahrscheinlich, daß es hier um Controller geht:
>
> Chris schrieb:
>> return EXIT_SUCCESS;
Das kam nur durch den Beispielcode von Galileo Computing zustande.
#3627376
Lesenswert?

Boahh schrieb:
> Ein Nullterminierter C-Stringist etwas vom Duemmlichsten, das man sich
> vorstellen kann.

Ich finde es genial.
Es macht die Verarbeitung sehr einfach und effizient.
Teilstrings lassen sich direkt parsen ohne ständige Kopier-Orgien.
Z.B. wenn ich ein Intel-Hex File einlese und binär in den Flash 
schreibe.

Boahh schrieb:
> Die Laenge braucht man ja eh sowieso.

Wozu denn?
Dann müßte ja mein Code haufenweise strlen() beinhalten, tut er aber 
nicht. Das ist eine der am wenigsten verwendeten Funktionen.
Z.B. ein Parser bricht einfach ab, sobald er das 0-Byte erkennt. Wann 
das ist, ist ihm sowas von egal.

Auch eine extra Längenangabe schützt überhaupt nicht vor Pufferüberlauf. 
Das muß jeder Programmierer selber absichern:
1
  if( idx >= sizeof(buffer))
2
    return ERROR;
3
  else
4
    buffer[idx] = irgendwas;

Oder man hat ein OS, was dynamisch Speicher vergrößert, sobald die 
aktuelle Länge überschritten wird. Das kostet natürlich massig Overhead.
#3627474
Lesenswert?

Peter Dannegger schrieb:
> Boahh schrieb:
>> Ein Nullterminierter C-Stringist etwas vom Duemmlichsten, das man sich
>> vorstellen kann.
>
> Ich finde es genial.
> Es macht die Verarbeitung sehr einfach und effizient.

Wenn man es von der einfachen Implementierbarkeit der Standardbibliothek 
absieht, ist eher das genaue Gegenteil der Fall. Siehe dazu z. B. den 
Artikel auf joelonsoftware, zu dem oben jemand einen Link gepostet hat 
und der den Unterschied zu "Pascal-Strings" erklärt (die zu Zeiten von 
Turbo Pascal gängig waren, in neueren Sprachen der Pascal-Familie wie 
Ada oder Delphi funktioniert das etwas anders und die Längengrenze von 
255 Zeichen ist entfallen).

> Teilstrings lassen sich direkt parsen ohne ständige Kopier-Orgien.
> Z.B. wenn ich ein Intel-Hex File einlese und binär in den Flash
> schreibe.

Das ist aber "Zufall", weil das Format von Intel-Hexfiles eben extra so 
entworfen wurde, daß es keine Binärdaten enthält. Würde man die Daten 
noch mal zwischenpuffern und mit C-Stringfunktionen weiterverarbeiten, 
so würde das höchstwahrscheinlich schiefgehen. Daher sollte man es 
dringend lassen, in C-Strings allgemeine Daten abzulegen. In Sprachen, 
die die Stringlänge unabhängig vom Inhalt speichern, kann man es dagegen 
riskieren, ich habe das früher in Turbo Pascal und Delphi öfters 
gemacht.

> Auch eine extra Längenangabe schützt überhaupt nicht vor Pufferüberlauf.
> Das muß jeder Programmierer selber absichern:
>
1
>   if( idx >= sizeof(buffer))
2
>     return ERROR;
3
>   else
4
>     buffer[idx] = irgendwas;
5
>

Das ist ein völlig anderes Problem, da geht es nicht um die fehlende 
Längenangabe in Strings, sondern die fehlende Längenprüfung von Arrays. 
Auch da bieten modernere Programmiersprachen Abhilfe.

In einem frühen Pascal-Compiler sind irgendwann Längenprüfungen für 
Arrays eingeführt worden und man hat dann daraufhin die User gefragt, ob 
man das Feature nicht aus Performancegründen abschaltbar machen sollte. 
Die meisten haben sich dagegen ausgesprochen, weil man damit offenbar so 
viele Fehler gefunden hat! Tatsächlich gehen die meisten 
Sicherheitslöcher in C-Programmen einschl. Heartbleed auf solche oder 
ähnliche Fehler zurück, die in moderneren Sprachen einfach kaum 
passieren können (es sei denn, man schaltet die Prüfungen ab, soweit das 
möglich ist).

> Oder man hat ein OS, was dynamisch Speicher vergrößert, sobald die
> aktuelle Länge überschritten wird. Das kostet natürlich massig Overhead.

In dem Moment, wo die Laufzeitbibliothek/Standardbibliothek einer 
Programmiersprache Funktionen für dynamische Strings enthält, kann man 
auch die Speicherverwaltung auf die schnelle Allokation und Deallokation 
kleiner Speichermengen optimieren. Gerade in Umgebungen, wo es nicht auf 
jedes Byte ankommt, gibt es weitere Optimierungsmöglichkeiten, z. B. daß 
man die Buffergröße und Stringlänge getrennt verwaltet, sodaß nicht jede 
kleine Änderung an einem String Allokations-, Kopier- und 
Deallokationsoperationen nach sich zieht.
Gast #3627718
Lesenswert?

"Das ist aber "Zufall", weil das Format von Intel-Hexfiles eben extra so
entworfen wurde, daß es keine Binärdaten enthält."

Binärdaten sind ja auch nicht unbedingt das, was man in einem String 
verarbeitet... Dafür bietet sich dann z.B. ein Array mit Längenangabe 
an.
#3627722
Lesenswert?

Peter II schrieb:
> Andy D. schrieb:
>> while (*dest++=*source++);
>>
>> Was soll da schon schiefgehen....

>nichts
Richtig. Wenn der Programmierer aufpasst.

Außerdem gibts ja auch noch die _s Funktionen, welche genau sowas 
verhindern sollen. Das da oben ist halt einfach mal ne echt schnelle und 
schlanke Methode. C halt. Nur hat C keine Sicherheitsgurte.

> (dest ist bestimmt ein objekt mit überladenen Operatoren)
Komischer Humor...
#3627907
Lesenswert?

Klaus Wachtler schrieb:
> cyblord ---- schrieb:
>> Außerdem gibts ja auch noch die _s Funktionen
>
> Die sind ja die größte Lachnummer. In speziellen Fällen gelegentlich
> "sicherer"...

Narrensicherheit wirst du halt bei C nicht finden. Das macht die Sprache 
nicht schlechter. Du kannst C nicht mit Pascal oder Java vergleichen. 
Wer die Freiheit von C nicht erträgt, kann sie duch die Sicherheit von 
höheren Sprachen aufgeben.

gruß cyblord
(Firma: JDCC) #3627914
Lesenswert?

Chris schrieb:
> Meine Funktion bekommt einen String übergeben, der auf einem LCD
> angezeigt wird. Dann gebe ich jedes Zeichen aus, bis der Inhalt 0 ist.
> Den Inhalt gebe ich im Quellcode vor, den Speicher werde ich also nicht
> überlasten. Ich könnte natürlich auch immer die Länge übergeben, aber so
> gefällt es mir besser.
Na wo ist dann das Problem ?

Du gibst selbst die Strings vor und niemand anders ändert die.
Ob Du das mit einer terminierenden 0 oder Längenangabe hoch 3
machst ist doch völlig egal.

Im schlimstem Fall erscheint Müll auf dem Display ;)
#3627934
Lesenswert?

cyblord ---- schrieb:
> Außerdem gibts ja auch noch die _s Funktionen, welche genau sowas
> verhindern sollen.

Unter einigen Betriebssystemen (ursprünglich OpenBSD, auch andere BSDs, 
Mac OS X, Solaris, ...) gibt es strlcpy() und strlcat(). Die Funktionen 
haben eine meiner Meinung nach außerordentlich gelungene Semantik, um 
strcpy() und strcat() weitestgehend zu ersetzen. Auf Plattformen, wo es 
sie nicht in der Standardbibliothek gibt, schreibe ich sie mir gerne 
selber.
Siehe dazu auch http://www.courtesan.com/todd/papers/strlcpy.html .
Gast #3631616
Lesenswert?

Andy D. schrieb:
> Es gab schon Programmfehler in der Geschichte bei denen es jahrelang
> funktionierte weil hinter dem String irgendetwas allokiert und immer zu
> dem Zeitpunkt auf 0 gesetzt war als dieser gelesen wurde...

Es gibt allgemein erschreckend viele Programme, die nur zufällig 
funktionieren.

Andy D. schrieb:
> @scheppertreiber wenn das eine bewusste und dokumentierte Optimierung
> ist ist es vielleicht kein Fehler, sonst schon ...

Ok, kann natürlich sein, daß es kein Fehler, sondern einfach nur 
schlechter Code ist.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren