PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : String initialisieren ohne 0 ?



Siro
02.03.2011, 10:12
Da bin ich schon wieder,
eine, nein eigentlich 2 Fragen zu Strings:

char s1[ ] = "Hallo";
char s2[5] = "Hallo";


Wenn ich schreibe: char s1[] = "Hallo";
werden 5+1 Byte belegt wegen dem Nullterminator.
Was ich durch den Versuch mit sizeof(s1) bestätigt bekommen habe.
Alles klar,

was passiert aber mit folgender initialisierung ?
char s2[5] = "Hallo";
Die Buchstaben passen ja noch rein, läst der Compiler den Nullterminator einfach weg, oder könnte es passieren, daß er das nächst liegende Byte hinter dem Array mit einer 0 beschreibt. Eine Warnung tritt zumindest nicht auf beim IAR Compiler. sizeof(s2)liefert auch logischerweise 5 zurück.

Dann käme als nächstes die Frage, was passiert beim Sring Compare der beident. Hier findert die function strcmp doch keine 0 am Ende von s2.
zumindest, vermutlich, nicht unmittelbar hinter dem Array s2, sondern zufällig irgendwann....

Ist diese Initialisierung von s2 also rechtens oder eher nicht ?

Siro

Felix G
02.03.2011, 10:43
Die zweite Variante ist gefährlich...

Ich bin nicht sicher ob für diesen speziellen Fall etwas im C-Standard spezifiziert ist, würde aber erstmal vom worst-case Fall ausgehen, nämlich daß der Compiler durchaus eine \0 hinter s2 schreiben könnte.

Aber selbst wenn er das nicht tut wird, wie du das bereits richtig erkannt hast, weder strcmp noch irgendeine andere Funktion korrekt arbeiten, die auf die \0 angewiesen ist (und das sind nahezu alle String-verarbeitenden Funktionen aus der Standardbibliothek).

Was du machen könntest, falls du das eine Byte wirklich zwingend einsparen musst und keine der Standardfunktionen nutzen möchtest, wäre folgende Initialisierung:


char s3[5] = {'H','a','l','l','o'};

Siro
02.03.2011, 14:07
Hallo Felix G,

Das "eine" Byte mehr im Array wäre mir im Prinzip egal, ich habe nur eine festgelegte Struktur, in der es ein ein 8 Byte großes Character Array gibt, weches ich initialisieren möchte, aber es später auch vergleichen möchte.

Also die Initialisierung könnte ich nach deiner Vorlage tätigen, dann bleibt jedoch noch das Problem der strcmp funktion offen.

Sinn und Zweck meines Vorhabens:
Ich habe in den letzten 8 Speicherstellen meines EEPROMs 8 Character, welche einen bestimmten String beinhalten müssen. Dies werden bei Programmstart einmal mit einem vorgegebenen String verglichen.

Dann werde ich mal aus Sicherheitsgründen nur einen 7 Zeichen langen String dort platzieren und eine Null anhängen, damit keine unerwarteten Ergebnisse auftauchen. Oder ich müste anstelle der strcmp funktion alle 8 Character separat vergleichen, ginge natürlich auch.

Mit der Array-Initialisierung nach deinem Prinzip kannte ich noch nicht
(bin ich nicht drauf gekommen) und danke Dir für die Info.
Siro

Ceos
05.03.2011, 15:52
wenn du s2 so wie oben initialisierst, würden die 5 bytes mit "hallo" beschrieben werden UND das nachfolgende byte mit einer 0, egal ob da ne variable kommt oder nicht ... es wäre in jedem falle ein "illegaler" zugriff den du vermeiden solltest ... wenn du irgendeine methode aufrufst die mit strings arbeitet, erwartet sie in er regel IMMER einen pointer und eine längenangabe, weil ein pointer nie weis wie groß der string ist auf den er zeigt

wenn du jetzt NACH s2 zum beispiel eine byte variable hast und diese VOR dem strcmp veränderst, erkennt er das ende des strings nicht mehr automatisch und es kann mörderisch krachen ^^

BurningWave
05.03.2011, 19:47
char s3[5] = {'H','a','l','l','o'}; ist doch bis auf die Schreibweise genau das gleiche, wie

char s2[5] = "Hallo";

und beides ist nicht empfehlenswert. Alle stringverarbeitenden Funktionen erwarten eine Nullterminierung. Falls du so eine Funktion benutzt, kann das in unerwartetem/unvorhersehbarem Verhaten enden, was auf einem µC besonders schlimm ist, da er entweder einen Reset macht oder du ihn evtl. zerschießen könntest.

EDIT: Erster Post im neuen Forum ;)

Felix G
05.03.2011, 19:55
char s3[5] = {'H','a','l','l','o'}; ist doch bis auf die Schreibweise genau das gleiche, wie

char s2[5] = "Hallo";Nein.
Bei meiner Variante wird keine \0 angehängt, bei der anderen schon.

{'H','a','l','l','o'} sind für den Compiler einfach nur 5 einzelne Zeichen, "Hallo" hingegen ist ein nullterminierter String.

Ceos
06.03.2011, 16:29
Nein.
Bei meiner Variante wird keine \0 angehängt, bei der anderen schon.

{'H','a','l','l','o'} sind für den Compiler einfach nur 5 einzelne Zeichen, "Hallo" hingegen ist ein nullterminierter String.
exakt, denn char s[n] ist nur ein array und kein string im eigentlichen sinn, bei der variante mit den anführungszeichen jedoch interpretiert er nur den anfang des arrays und wird VERMUTLICH das nachfolgende byte mit einer 0 versehen ... die problematik die ich angesprochen habe bezog sich auch eher auf die spätere verwendung, wobei die terminierende 0 zufällig erhalten werden KÖNNTE aber auch durch eine andere variable verändert werden KÖNNTE ... und das wie oben schon gesagt zum controller absturz füren kann

Cid
18.03.2011, 16:59
naja.... ob er jetzt Strings nutzt oder nicht, ist ihm überlassen - wenn er weiß, dass es x Zeichen sind, kommt er auch ohne \0 aus...
statt vergleiche solange bis \0 in einem String erreicht kann man auch irgendwie sowas machen...

//a sei die Eingabe, b sei das fest gespeicherte, x sei die bekannte Länge von b
for (i = 0; i < x; i++) {if (a[i] != b[i]) || (a[i] == '\0') return false;}
if (a[x] != '\0') return false;
return true;

AAAAABäääääär für die Eingabe der Daten:
pass bei C-Code auf, man weiß nie, ob alle Compiler (Windows/Linux/..., offiziell/alternative/...) die Spezifikationen perfekt einhalten...
nicht dass ein Compiler meckert, weil es für ihn 6 Zeichen sind, einer das einfach richtig abarbeitet (\0 wegschmeißen) und ein anderer es verbockt es (hängt \0 an und verschiebt alles)
(letztens erst nen Compiler geschrieben, man glaubt nicht was eine Umstellung an der Spezifikation bewirken kann)

also lieber statt "Hallo", was zurechtgeschnitten werden müsste,
ein sauberes {'H',...,'o'}, das Char[] einfach als Byte[] interpretiert...

markusj
18.03.2011, 17:45
Naja, dann kann man das Programmieren auch gleich sein lassen, wenn man sich nicht auf die Sprachspezifikation stützen (kann). Der Standard sagt klar aus, dass nur der Speicher des Arrays beschrieben wird, alles andere ist ein Fehler im Compiler.

mfG
Markus

PS: http://www.dclc-faq.de/kap5.htm#5.20