-         

Ergebnis 1 bis 7 von 7

Thema: String terminator bei const char

  1. #1
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    05.11.2007
    Ort
    Berlin
    Beiträge
    525

    String terminator bei const char

    Anzeige

    Hallo,
    ich bin mal wieder am Programmcode kürzen und habe dazu eine vermutlich simple Frage:
    Doch zunächst die 2 Programmzeilchen:

    const char Password[] = "Hello";
    #define PASSWORD_LEN sizeof(Password)-1


    Meine Frage dazu:
    Hängt ein C-Compiler IMMER eine 0x00 (Stringterminator) bei obiger Definition ? Dann muss ich nämlich -1 angeben.

    Warum ich das mache ?

    Durch diese Definition erspare ich mir später im Code mittels "strlen" auf die Länge zu zugreifen. Ich könnte auch eine 5 für die Länge eintragen, aber das finde ich äußert unschön, wenn man den Text ändert, müste auch der Wert geändert werden.

    Sinn und Zweck:
    Wenn ich über die serielle Schnittstelle ein Zeichen empfange, wird dieses mit einem Zeichen des Passworts verglichen. Ist das Zeichen okay, wird mein StringIndex erhöht. Hat der StringIndex die Länge erreicht,wurde das komplette Passwort erkannt. Bei jeglichem falschen Zeichen wird der Index wieder auf 0 gesetzt.

    if (SringIndex == PASSWORD_LEN) .....
    ist halt wesentlich kürzer und schneller als

    if (StringIndex == strlen(Password))

    Bei einem hohen Datenaufkommen wäre es unnützer Ballast mit dem strlen.

    Ich möchte aber nicht, daß diese Vorgehensweise Compiler spezifisch ist.

    Darum die Frage, wird bei const char xx = "xxx" IMMER eine 0 angehangen. bzw bei dem sizeof() immer Anzahl der Buchstaben +1 geliefert.Oder könnte es sogar passieren, daß sizeof etwas "dazu packt"
    wegen Word Aligned oder ähnlichem.

    Danke für Eure Info.
    Siro

  2. #2
    Erfahrener Benutzer Roboter Experte Avatar von BurningWave
    Registriert seit
    22.12.2007
    Ort
    nahe Stuttgart
    Alter
    23
    Beiträge
    656
    Das Array Password hat 6 Elemente, wobei Array[5] '\0' ist, also 0.
    sizeof(Password) wird dementsprechend 6 (6 * sizeof(char)) zurückgeben. Jeder char* String wird mit 0 terminiert in C/C++.

    Dir ist hoffentlich klar, dass der Compiler bei deiner Makrodefinition nicht den Ausdruck ausrechnet und das Ergebnis überall einfügt, sondern den kompletten Ausdruck an Stelle des Makros einfügt.
    meine Homepage: http://www.jbtechnologies.de
    Hauptprojekte: Breakanoid 2 - Sound Maker

  3. #3
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    C (++) hängt bei strings generell \0 an. (heisst ASCIZ)
    Denn alle standard string-functions von C verlangen NULL-terminierte strings
    strcpy, strcmp, .....
    Stammt, denk' ich, vom INTEL i386-Assembler, da gibt es diese "REPZ" Befehls-prefixe, d.h. der Maschinen code unterstützt das.

    Ich glaub', bei Pascal werden dagegen für Strings "Counted strings" verwendet, da ist das erste Byte immer die Anzahl Zeichen dahinter. (ASCIC)

    Beides hat Vor- und Nachteile.
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  4. #4
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    25.03.2006
    Ort
    Darmstadt
    Alter
    26
    Beiträge
    522
    Noch ein kleiner Hinweis: mach ein paar Klammern um "sizeof(Password)-1" herum. Sollte man nämlich mal irgendwann PASSWORD_LEN*2 schreiben, wird man mit der obigen Definition eine böse Überraschung erleben.

    MfG Mark

  5. #5
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    05.11.2007
    Ort
    Berlin
    Beiträge
    525
    zu _R2D2
    ich denke, bzw. ich hoffe doch, daß der Compiler stets den ausgerechneten Wert, in diesem Falle 6 einsetzt. Dafür sorgt der "Preprozessor" wenn ich mich nicht irre. Das Define wir doch vom Preprozessor ausgewertet, bevor der Compiler überhaupt loslegt. Also sollte der Compiler eigentlich immer diese entsprechend vorausberechnete Konstante einsetzen. Aber ehrlich gesagt hab ich keine wirkliche Ahnung von Compilern, wies sie etwas auswerten. Aber entscheidend für mich ist deine Aussage:
    Jeder char* String wird mit 0 terminiert in C/C++.
    Damit liegt meine Software rechnerisch also immer richtig.


    zu PicNick:
    Jou, bei den Intels gab, bzw. gibt es diese Befehle "REPZ STOSW"
    Repeat Until Zero, Speicher den Wert an ESI oder auch "REPZ MOVSB" kopiere alle Werte von DS:SI nach ESI wobei hier der "Zero" Bezug glaube ich auf das "CX" Register bezogen wurde, nicht auf ein "0" Vorkommen innerhalb des Speichers. Ist aber schon ein Weilchen her, könnte mich auch irren. Bei Pascal kenne ich mich recht gut aus, da steht in dem ersten Byte (Array[0]) immer die Länge des Strings. Dafür wurden aber auch bei String Variablen gleich 256 Bytes reserviert, wenn man nicht
    separat eine feste Länge angegeben hat. Maximal war ein String halt 255 Zeichen. Ein strlen war aber hier durch direkten Zugriff auf das Byte mit dem index 0 möglich. Bei Nullterminierten Strings (wie bei C) muss man erst "suchen" wo isse denn die olle Null..... Dafür gibts halt keine Längenbegrenzung bei den "Null Terminierten" Wie Du schon sagst, hat alles Vor und auch Nachteile.

    zu p_mork:
    Danke für den Hinweis mit den Klammern, das vergesse ich immer wieder und bin schon fürchterlich auf die Schna..e damit gefallen.
    Absolut berechtigt hier Klammern zu setzen.
    sizeof(Password)-1*2
    ist dann doch "etwas unterschiedlich" zu
    (sizeof(Password)-1)*2

    So Leute, morgen ist der 1. Advent, ich Danke Euch und wünsche noch ein ruhiges Wochenende.
    Siro

  6. #6
    Erfahrener Benutzer Robotik Einstein Avatar von Felix G
    Registriert seit
    29.06.2004
    Ort
    49°32'N 8°40'E
    Alter
    34
    Beiträge
    1.780
    Zitat Zitat von Siro
    ich denke, bzw. ich hoffe doch, daß der Compiler stets den ausgerechneten Wert, in diesem Falle 6 einsetzt. Dafür sorgt der "Preprozessor" wenn ich mich nicht irre. Das Define wir doch vom Preprozessor ausgewertet, bevor der Compiler überhaupt loslegt. Also sollte der Compiler eigentlich immer diese entsprechend vorausberechnete Konstante einsetzen.
    Das funktioniert so leider nicht...

    Der Präprozessor ist ziemlich dumm, und macht bei einem #define nichts anderes als ein "Search & Replace". Er ersetzt im Quellcode also nur jedes "PASSWORD_LEN" das er findet durch "sizeof(Password)-1".
    Wenn der Compiler dann den so vorbereiteten Quellcode verarbeitet, kann er natürlich noch Optimierungen machen (z.B. konstante Ausdrücke vorberechnen), aber das macht er eh immer - egal ob mit oder ohne Präprozessor.

    Aus diesem Grund kann es zu Problemen führen, wenn du in einer anderen Quelldatei als der in der du deinen String definiert hast, dessen Länge wissen möchtest. Denn der Compiler übersetzt jede Datei einzeln, und weiß daher nicht wie groß das Array tatsächlich ist. Das resultiert dann entweder in einer Fehlermeldung (Idealfall), einer Warnung (nicht so toll weil man sie ignorieren kann), oder er rechnet einfach mit den Informationen die er zur Verfügung hat (nämlich "Password hat den Typ char*, und der hat die Größe 4") was mit hoher Wahrscheinlichkeit ein völlig falsches Ergebnis liefert.
    So viele Treppen und so wenig Zeit!

  7. #7
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    Ich stelle mit leichter Häme fest, dass deine Beziehung zu C im Laufe der letzten Wochen erstaunlich moderat geworden zu sein scheint Offenbar setzt mit der Beschäftigung damit eine geistige Defomierung ein, damit man das,, was man bei gesundem Verstand noch als Sonderzeichen-Irrwitz gesehen hat, schön langsam als gottgegeben normal empfindet.

    Welcome to the party
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •