Forum: Compiler & IDEs Strings ohne Null am Ende?


von df1as (Gast)


Lesenswert?

Hallo!

Wie bekomme ich die Null am Ende eines (eigentlich Zero-terminierten) 
Strings weg?

Beispiel:
1
char achComment[6] = "123456";                       // zu lang
2
char achComment[6] = {'1', '2', '3', '4', '5', '6'}; // zu umständlich

Mit einem Cast vor dem String (z. B. typedef char ach6[6] => (ach6) 
"123456") geht's auch nicht. Ich muss ein Array als Aggregat 
initialisieren mit einigen hundert längeren Strings, die bereits fertig 
formatiert vorliegen. Mit der Aufspaltung in einzelne Zeichen ('1', '2' 
...) sprengt das das Gesamtbild und ist dann auch nicht mehr lesbar. Zur 
Laufzeit möchte ich auch nichts umformatieren.

Käme man mit Macros weiter? Wenn ja, wie?

: Gesperrt durch Moderator
von Udo S. (urschmitt)


Lesenswert?

Was willst du erreichen?
Welchen Sinn machen nicht 0 terminierte Strings in C?

von Karl H. (kbuchegg)


Lesenswert?

> char achComment[6] = "123456";                       // zu lang

Nö.
In diesem Fall hängt der Compiler kein \0 Byte an.
Die Frage bleibt aber immer noch: Wozu?

von Klaus W. (mfgkw)


Lesenswert?

geht halt nicht.

Bei "..." ist immer die 0 dabei, ohne Gänsefüßchen nicht - aber das 
gefällt dir ja nicht.

von df1as (Gast)


Lesenswert?

Ich habe ein Array mit fest vorgegebenen Strukturen. Dort sind an einer 
Stelle 48 ASCII-Zeichen vorgesehen (größtenteils lesbarer Text), die 
ganz einfach keine Null am Ende haben und entweder bis ans Ende mit 
Spaces aufgefüllt oder komplett ausgenutzt sind.

Interessanterweise kann man Strings ja auch zusammensetzen, z. B. "123" 
"456" "789", sogar mit Zeilenumbruch dazwischen. Hinter das letzte 
Zeichen kommt dennoch unweigerlich eine Null.

Ich habe schon mit folgendem Macro getestet:
1
#typedef mTxt(a) {a[0],a[1],a[2],a[3],a[4],a[5]}
2
...
3
char achComment[6] = mTxt("123456");
... geht sytaktisch auch nicht. Ich denke aber, dass das die richtige 
Richtung sein müsste.

von Udo S. (urschmitt)


Lesenswert?

df1as schrieb:
> Ich habe ein Array mit fest vorgegebenen Strukturen. Dort sind an einer
> Stelle 48 ASCII-Zeichen vorgesehen (größtenteils lesbarer Text), die
> ganz einfach keine Null am Ende haben und entweder bis ans Ende mit
> Spaces aufgefüllt oder komplett ausgenutzt sind.
Nochmal: Wozu sollen diese Felder taugen in C?
Du kannst keine Standard Stringfunktionen von C darauf anwenden. Weder 
zur Ausgabe noch zur Manipulation. Die sind praktisch nutzlos.
Du wirst diese Felder dann wie binärdaten behandeln müssen und dir 
irgendwo die Länge merken. Das macht in der Regel überhaupt keinen Sinn!

von df1as (Gast)


Lesenswert?

Ja, viele Dinge im Leben machen keinen Sinn ...

von Yalu X. (yalu) (Moderator)


Lesenswert?

> char achComment[6] = "123456";                       // zu lang

In C ist das in Ordnung und hat den gewünschten Effekt, in C++ ist es
ein Fehler. Dort kommst du um die Schreibweise mit den einzelnen Char-
Konstanten wahrscheinlich nicht herum.

von Nils S. (kruemeltee) Benutzerseite


Lesenswert?

df1as schrieb:
> Ja, viele Dinge im Leben machen keinen Sinn ...

Auch dass irgend etwas Sinn machen könnte ist sinnlos, denn machen 
bedeutet etwas (greifbares) schaffen.

von Karl H. (kbuchegg)


Lesenswert?

Klaus Wachtler schrieb:
> geht halt nicht.
>
> Bei "..." ist immer die 0 dabei,

Nicht ganz.
Es gibt eine Ausnahme.
Wenn der String (nur die Zeichen ohne abschliessendes \0) knirsch ins 
Array passt, dann hängt der COmpiler kein \0 an.

char command[6] = "12345";     // ok, \0 Byte angehänt
char command[6] = "123456";    // auch ok, kein \0 Byte angehängt
char command[6] = "1234567";   // warning: initializer too long


(und genau aus dem Grund ist es normalerweise dämlich die Arraylänge 
vorzugeben und nicht vom Compiler abzählen zu lassen)

von Yalu X. (yalu) (Moderator)


Lesenswert?

df1as schrieb:
> #typedef mTxt(a) {a[0],a[1],a[2],a[3],a[4],a[5]}
> ...
> char achComment[6] = mTxt("123456");
> ... geht sytaktisch auch nicht.

... weil es nicht #typedef, sondern #define heißt. Dann funktioniert das
schon, allerdings eben nur mit einer festen Arraylänge.

von ErgoProxy (Gast)


Lesenswert?

Wie wäre es einfach mit einer Funktion durch den String zu gehen und 
alle Zeichen in das Zielarray zu schreiben und bei der 0 aufzuhören?

Gruß Andi

von Peter S. (psavr)


Lesenswert?

>Es gibt eine Ausnahme.
>Wenn der String (nur die Zeichen ohne abschliessendes \0) knirsch ins
>Array passt, dann hängt der COmpiler kein \0 an.

Ist das per C Standard so definiert, oder liegt das in der 
Interpretationsfreiheit des zufällig gewählten Compilers?

von Karl H. (kbuchegg)


Lesenswert?

Peter S. schrieb:
>>Es gibt eine Ausnahme.
>>Wenn der String (nur die Zeichen ohne abschliessendes \0) knirsch ins
>>Array passt, dann hängt der COmpiler kein \0 an.
>
> Ist das per C Standard so definiert, oder liegt das in der
> Interpretationsfreiheit des zufällig gewählten Compilers?

Ist so definiert.

Frag mich aber nicht, wo da der Sinn liegt. Stammt wahrscheinlich noch 
aus der Zeit als jedes Byte RAM kostbar war. Weit, weit vor unserer 
Zeit, lange vor dem großen Krieg.

von Lord Z. (lordziu)


Lesenswert?

df1as schrieb:
> Ja, viele Dinge im Leben machen keinen Sinn ...

Was man dir hier versucht zu erklären ist, dass du deine Daten auf 
unterschiedlichen Wegen verwalten kannst.

1) Als String

Also zum Beispiel
char foo[4] = "abc"; // abc mit \0 als Abschluss

Das macht man, wenn man diese Daten als string weiter verarbeiten will. 
Sprich, wenn man die String-Funktionen der C Bibliotheken verwenden 
möchte. Diese Funktionen basieren alle darauf, dass der String mit einem 
'\0' abgeschlossen ist. Sonst können sie das Ende nicht erkennen.

Wer damit arbeiten will, muss seine char-Buffer immer ein Byte größer 
machen, als der String lang ist, damit man das '\0' noch unterbekommt.

2) Als "normale" Daten

Wenn man KEINE String-Funktionen benutzen will, hindert dich niemand 
daran die Daten z.B. in ein uint8_t Array zu packen. Da hast du dann 
immer die Länge der Daten == Länge des Arrays.

Initialisieren könnte man dass dann zum Beipiel mit memset. Oder aus 
einer anderen Quelle kopieren mit memcpy.



Die Frage ist doch erstmal, woher kommen deine Daten und wie willst du 
sie weiterverarbeiten?

von df1as (Gast)


Lesenswert?

Ja, sry. War schon #define, nicht typedef. Vom Prinzip her müsste das 
mit dem Macro gehen. Vermutlich bin ich mit der Macro-Syntax mit einem 
String als Parameter nur nicht firm.

Dass es mit C statt C++ mit dem Abschneiden der Null gehen soll, wäre 
auch eine Lösung. C sollte aber eine Untermenge von C++ sein. Gibt es 
vielleicht ein #pragma, mit dem man das String-Abschneiden (wieder) 
einschalten kann?

von Karl H. (kbuchegg)


Lesenswert?

df1as schrieb:

> Dass es mit C statt C++ mit dem Abschneiden der Null gehen soll, wäre
> auch eine Lösung. C sollte aber eine Untermenge von C++ sein.

Das ist schon mal der erste Fehler.
C ist schon lange keine Untermenge von C++ mehr.
C++ und C sind 2 verschiedene Sprachen. Und so sollte man das auch 
behandeln.

> Gibt es
> vielleicht ein #pragma, mit dem man das String-Abschneiden (wieder)
> einschalten kann?

Wenn überhaupt, dann weiß das die Doku zu deinem Compiler (pragma ist 
immer compilerspezifisch). Ich wüsste allerdings keinen einzigen 
Compiler der das macht.

Aber: die meisten Systeme können C und C++ insofern mischen, dass man 
die beiden einfach zusammenlinken kann. Gib deine Initialisierungen in 
ein eigenes File und kompiliere es mit einem C-Compiler. Viele Compiler 
sind Kombi-compiler, die sowohl C++ als auch C können. Entweder gibt es 
dafür einen Commandline Switch oder sie benutzen die Dateiendung um zu 
entscheiden, welcher Modus benutzt werden soll.



Das die meisten das Ganze trotzdem nicht für eine gute Idee halten, ist 
ja jetzt schon oft genug ausgesprochen worden. Daher spar ich mir eine 
weitere Wiederholung.

von df1as (Gast)


Lesenswert?

Also ... die Daten sind einige kB lang und zur Übertragung in eine ca. 
15 Jahre alte Steuerung vorgesehen. Am Format kann man nicht mehr 
rütteln. Die Inhalte der Daten liegen auch fertig formatiert vor.

Die Schreibweise mit einzelnen Zeichen ist ja möglich, aber aus 48 
Zeichen werden dann schon mal 192 geplenkt, sonst 240. Wenn's mit dem 
Macro nicht klappt, muss ich diesen Weg dann wohl nehmen - oder auf 
Assembler, ggf. inline, umsteigen.

von df1as (Gast)


Lesenswert?

Compiler ist Visual Studio 10.

Es gibt dort etliche Optionen zum Verkurbeln. Ich schaue mal.

von Karl H. (kbuchegg)


Lesenswert?

df1as schrieb:
> Also ... die Daten sind einige kB lang und zur Übertragung in eine ca.
> 15 Jahre alte Steuerung vorgesehen. Am Format kann man nicht mehr
> rütteln. Die Inhalte der Daten liegen auch fertig formatiert vor.

Ich seh da jetzt das Problem immer noch nicht.
Wenn dein C++ Programm, das alles übertragen soll, hindert dich ja 
niemand daran, im C++ Programm das abschliessende \0 Byte nicht zu 
übertragen, wenn es die Steuerung so haben will. Deswegen muss man sich 
doch keine Krücken ins  Übertragungsprogramm holen.

Aber dazu wissen hier alle zu wenig von deinem System um da irgendeine 
vernünftige Aussage zu machen. Die Erfahrung ist halt, dass sich 
Programmierer oft in einen Weg verbeissen, der neutral gesehen nicht der 
schlaueste ist. Und derartige 'Künstelaktionen' sind halt oft nicht der 
schlaueste Weg, weil umständlich und fehleranfällig.
Und das fängt schon damit an, warum die Texte im Programm sind und nicht 
von einem File eingelesen werden.

von Udo S. (urschmitt)


Lesenswert?

df1as schrieb:
> char achComment[6] = {'1', '2', '3', '4', '5', '6'}; // zu umständlich

df1as schrieb:
> Wenn's mit dem
> Macro nicht klappt, muss ich diesen Weg dann wohl nehmen - oder auf
> Assembler, ggf. inline, umsteigen.

Und das ist weniger umständlich?

Na dann mach mal.

von Karl H. (kbuchegg)


Lesenswert?

df1as schrieb:
> Compiler ist Visual Studio 10.

Dann ist es doch simpel.
Di C++ Files haben die Endung .cpp
C-Files haben die Endung .c

Fertig.

von df1as (Gast)


Lesenswert?

Ja, das Macro muss ich nur einmal schreiben, nicht ein paar hundert 
Male.
1
#define mT(a) ...
2
3
tstStrukturArray[] = {
4
{32, 0, 100, 600, mT("Hier steht der lange Kommentar     "),{{101,18},{...
5
{32, 1, 100, 600, mT("Hier steht der naechste Kommentar  "),{{100,10},{...
6
{32, 2, 100, 600, mT("Hier steht der uebernaechste       "),{{105,11},{...

So in etwa.

Natürlich kann ich auch das Kommentarfeld ein Zeichen länger definieren 
und dann per Programm selbiges wieder aussparen oder von einer 
Initialisierungsstruktur in eine Ausgangsstruktur umformatieren. Das 
wollte ich nicht, weil es vielleicht schneller gegangen wäre, wenn ... 
aber erstens kommt es mal wieder anders und zweitens als man denkt.

von Karl H. (kbuchegg)


Lesenswert?

Ich hab allerdings das ganz starke Gefühl, dass da wieder mal wer "Daten 
die über eine Schnittstelle übertragen werden" und "Daten die im 
Programm gespeichert werden" durcheinanderwirft.

von Karl H. (kbuchegg)


Lesenswert?

df1as schrieb:

> Natürlich kann ich auch das Kommentarfeld ein Zeichen länger definieren
> und dann per Programm selbiges wieder aussparen oder von einer
> Initialisierungsstruktur in eine Ausgangsstruktur umformatieren. Das
> wollte ich nicht, weil es vielleicht schneller gegangen wäre, wenn ...

Nur so als Tipp:
Du wärst schon längst damit fertig.

Zumal es sowieso unklug ist eine STruktur einfach so als Ganzes über 
eine Schnittstelle an ein bereits bestehendes System zu übertragen. 
Schon mal was von Padding Bytes gehört? Oder davon, dass int je nach 
System mal 2, mal 4 oder auf den neuen Systemen gar 8 Bytes hat. Oder 
dass die Byte Order nicht genormt ist oder ...

Mach dir eine Funktion, die die Einzelteile der STruktur schön 
nacheinander einzeln auf den Weg bringt. Und dort kommt dann die 
Sonderbehandlung für den Text rein. Da kannst du dann auch zu kurze 
Texte mit Leerzeichen auffüllen.

von Clemens M. (panko)


Lesenswert?

Du ignorierst du hilfreichen Gegenfragen geflissentlich...
Die Frage, ob dein gewünschtes Vorgehen überhaupt notwendig, hilfreich 
oder gar nützlich ist würde ich mir durch den Kopf gehen lassen.
Manchmal ist man ja auch dem Holzweg. Oder bekommt eine Aufgabe die 
ebenfalls auf einem Holzweg basiert.

edit. OK hat sich einiges getan während des Schreibens.

von df1as (Gast)


Lesenswert?

Ja klar wäre ich schon fertig. So gesehen. Aber eine kleine 
Herausforderung ist das schon und da gebe ich eigentlich nur ungern 
klein bei.

von Cyblord -. (cyblord)


Lesenswert?

df1as schrieb:
> Ja klar wäre ich schon fertig. So gesehen. Aber eine kleine
> Herausforderung ist das schon und da gebe ich eigentlich nur ungern
> klein bei.

Ein Problem mit einem völlig falschen Programmieransatz lösen zu wollen 
ist keine "Herausforderung" sondern dämlich.

von df1as (Gast)


Lesenswert?

Bitte erst die Aufgabenstellung lesen, dann verstehen, dann sich zu Wort 
melden, wenn man einen undämlichen Beitrag beisteuern kann ...

In dieser "Aufgabenstellung" geht es ja gerade nicht um ein Programm, 
sondern um eine (etwas spezielle) Aggregatinitialisierung in lesbarer 
Form, nicht weniger aber auch nicht mehr. Nur Präprozessor und Compiler 
sollten etwas zu tun bekommen.

Danke erstmal für alle konstruktiven Vorschläge. Der Wechsel von C++ auf 
C hatte im Visual Studio keine Auswirkungen, alle Einstellungen sind 
dort unter der Rubrik "C/C++" vereint - wohl wegen der gewünschten 
Abwärtskompatibilität. Derweil benutze ich die "unlesbare" Variante.

...-.-

von df1as (Gast)


Lesenswert?

Als Nachtrag hier noch eine lauffähige Makrolösung:
1
#define mT(a) {((const char*)a)[0],((const char*)a)[1],((const char*)a)[2] ...}
2
...
3
tstMyStruct astMyArrayOfStructs[] = {
4
{32, 0, 100, 600, mT("Hier steht der lange Kommentar     "),{{101,18},{...
5
{32, 1, 100, 600, mT("Hier steht der naechste Kommentar  "),{{100,10},{...
6
{32, 2, 100, 600, mT("Hier steht der uebernaechste       "),{{105,11},{...

Entspricht bereits meinem ersten Makroversuch, nur der Compiler benötigt 
wohl noch eine Typdeklaration. Mit "String"[n] geht's also nicht, mit 
((const char*)"String")[n] schon.

von Nils S. (kruemeltee) Benutzerseite


Lesenswert?

df1as schrieb:
> In dieser "Aufgabenstellung" geht es ja gerade nicht um ein Programm,
> sondern um eine (etwas spezielle) Aggregatinitialisierung in lesbarer
> Form

Und wer macht das? Das Programm.

Die Lösung wurde schon mehrfach genannt. Arbeite mit 0-terminierten 
Strings. Kein Compiler und keine Sprache zwingt dich, die mitzusenden, 
falls du sie nicht brauchst.

Bei Array-Verwendung brauchst du einen index für die Länge oder musst 
mit festen Längen arbeiten und du kannst die Stringfunktionen der 
Standardlibrary nicht verwenden.

von Karl H. (kbuchegg)


Lesenswert?

df1as schrieb:

> In dieser "Aufgabenstellung" geht es ja gerade nicht um ein Programm,
> sondern um eine (etwas spezielle) Aggregatinitialisierung in lesbarer
> Form, nicht weniger aber auch nicht mehr. Nur Präprozessor und Compiler
> sollten etwas zu tun bekommen.


Du versuchst gerade die Aufgabenstellung zu lösen
"Wie kann ich in 3000 Meter Wassertiefe nur mit einer Badehose 4 Wochen 
überleben"
wenn die richtige Problemlösung darin besteht, einfach eine Reling am 
Schiff anzubringen, so dass du gar nicht erst über Bord gehst und für 
den Fall des Falles eine Schwimmweste anlegen musst.

Manchmal ist eine sich ergebende "Aufgabenstellung" einfach nur ein 
Indiz, dass das Problem einer anderen Lösungsstrategie bedarf. Es bringt 
nichts, dieser Aufgabenstellung nachzulaufen, weil man dann einfach nur 
einen Haufen Aufwand für nix hat.

von Cyblord -. (cyblord)


Lesenswert?

df1as schrieb:

> In dieser "Aufgabenstellung" geht es ja gerade nicht um ein Programm,

Alles klar, mein Fehler. Ich dachte es geht ums programmieren, vorallem 
weils in der Rubrik "gcc" steht.

> sondern um eine (etwas spezielle) Aggregatinitialisierung in lesbarer
> Form, nicht weniger aber auch nicht mehr.

Namentlich um das Befüllen von structs, mit Strings welche aber nicht 0 
terminiert sind und deshalb im engeren Sinne von C also auch überhaupt 
gar keine Strings sind. Aha. Aber WARUM und zu welchem Zweck diese 
absolute Krücke von Initaliserung gemacht wird inkl. einem 
Monster-Define bleibt schleierhaft und genau dieses WARUM scheint die 
Wurzel deines Übels zu sein. Aber du hörst einfach nicht auf die Leute 
hier die dir das sagen wollen.
Beratungsresistent hoch 10. Denn es gibt einfach keinen vernünftigen 
Grund warum dies so machen sollte wie du es vor hast.

Hast du denn überhaupt überprüft ob das direkt gesendete Array und 
dessen Structs von Zielsystem auch so verstanden werden? Wie die 
Vorredner schon angemerkt haben kann da im Bereich Datentyplänge und 
Byteorder einiges schiefgehen.

von df1as (Gast)


Lesenswert?

Nein, nix geht schief und alles passt jetzt. Danke für die Nachfrage.

Zumindest packt der MS-Compiler alles fix und fertig in nur die eine 
Variable bzw. Konstante. Kann aber schon sein, dass ein GCC oder 
sonstiger Compiler das nicht so elegant hinbekommt. Ohne eingeschaltete 
Optimierung sieht's mit Visual auch leicht verwegen aus (fummelt dann 
die Strings in den Strukturen im Startup-Code zusammen), aber dazu 
gibt's die Optimierung ja u. a.

Besser, wieder was dazugelernt zu haben (übrigens nach über 30 Jahren 
Programmiererfahrung auf etlichen Plattformen meinerseits), als durch 
wie auch immer geartete Beratung in Richtung Lernresistenz unterwegs zu 
sein.

...-.-

von superstru (Gast)


Lesenswert?

huhu,
ich schalte mich kurz mal ein..

für das problem des fragestellers:
ich würde ein kleines script in scriptsprache meiner wahl schreiben 
welches mir aus den strings eine hübsche variablendefinition in c array 
ausgibt.
also aus "abc" dann 'a','b','c',' ',.. macht.

für das anliegen: strings ohne null
hab mal gelesen dass die erfinder der sprache c eben diese 
nullterminierten strings als eine ihrer größten fehlentscheidungen 
ansahen - führte zu buffer overflows und anderen problemen.
in der schule hatte ich damals pascal gelernt - dort haben die strings 
zuerst ein byte mit länge, dann folgen die zeichen. beschränkung ist so 
auf max. 255 zeichen festgesetzt.
meine frage ist: gibt es ähnliches für c? wohl nicht, sonst hätte ich es 
schon gefunden.
und festbreitenstrings könnten manchmal auch ihren sinn haben - als eben 
alternative, ähnlich wie integer mit signed/unsigned.

von Udo S. (urschmitt)


Lesenswert?

superstru schrieb:
> in der schule hatte ich damals pascal gelernt - dort haben die strings
> zuerst ein byte mit länge, dann folgen die zeichen. beschränkung ist so
> auf max. 255 zeichen festgesetzt.
Das ist auch nicht besser. Als ich damals von Pascal auf C umgestiegen 
bin waren nicht längenbegrenzte Strings einer der wichtigsten Vorteile 
von C. Genauso wie die konsequente und transparente Verwendung von 
Zeigern.
Aber die Welt ist seitdem ja nicht stehen geblieben

Karl Heinz Buchegger schrieb:
> Du versuchst gerade die Aufgabenstellung zu lösen
> "Wie kann ich in 3000 Meter Wassertiefe nur mit einer Badehose 4 Wochen
> überleben"
> wenn die richtige Problemlösung darin besteht, einfach eine Reling am
> Schiff anzubringen, so dass du gar nicht erst über Bord gehst und für
> den Fall des Falles eine Schwimmweste anlegen musst.
ROFL der trifft es ganz gut.

df1as schrieb:
> In dieser "Aufgabenstellung" geht es ja gerade nicht um ein Programm,
> sondern um eine (etwas spezielle) Aggregatinitialisierung in lesbarer
> Form,

df1as schrieb:
> Als Nachtrag hier noch eine lauffähige Makrolösung:#define mT(a) {((const 
char*)a)[0],((const char*)a)[1],((const char*)a)[2] ...}
> ...
> tstMyStruct astMyArrayOfStructs[] = {
> {32, 0, 100, 600, mT("Hier steht der lange Kommentar     "),{{101,18},{...
> {32, 1, 100, 600, mT("Hier steht der naechste Kommentar  "),{{100,10},{...
> {32, 2, 100, 600, mT("Hier steht der uebernaechste       "),{{105,11},{...

Und DAS nennst du lesbar???????????????
Klar der Text ist lesbar, aber der Rest....

von Detlev T. (detlevt)


Lesenswert?

superstru schrieb:
> hab mal gelesen dass die erfinder der sprache c eben diese
> nullterminierten strings als eine ihrer größten fehlentscheidungen
> ansahen - führte zu buffer overflows und anderen problemen.

Hast du dafür eine Quelle? Buffer Overflows wären ja auch mit der 
Pascal-Längenbyte möglich, dafür ist die Gesamtlänge des Strings 
willkürlich beschränkt.

von Karl H. (kbuchegg)


Lesenswert?

Detlev T. schrieb:
> superstru schrieb:
>> hab mal gelesen dass die erfinder der sprache c eben diese
>> nullterminierten strings als eine ihrer größten fehlentscheidungen
>> ansahen - führte zu buffer overflows und anderen problemen.
>
> Hast du dafür eine Quelle?

Würde mich jetzt auch interessieren.

Denn das größte Problem in C sind nicht 0-terminierte Strings, sondern 
die Art und Weise, wie Arrays behandelt werden. Der Array-Pointer 
Dualismus hat seine Vorteile, hat aber auch seine Nachteile. 
0-terminierte Strings können da genau gar nichts dafür.

Das, und die Einführung der Funktion gets(), sind die IMHO die größten 
Problemkreise in C. Wobei man letzteres einfach korrigieren könnte, 
ersteres aber nicht.

von Bartli (Gast)


Lesenswert?

Das eigentlich Bescheuerte an nullterminierten Strings ist doch die 
Komplexität von O(N) zum Bestimmen ihrer Länge, aber das hat nichts mit 
Bufferoverruns zu tun, die kann ich auch mit std::string produzieren 
wenn ich will :D

von Peter II (Gast)


Lesenswert?

Bartli schrieb:
> Das eigentlich Bescheuerte an nullterminierten Strings ist doch die
> Komplexität von O(N) zum Bestimmen ihrer Länge

die Frage ist für was man die länge überhaupt braucht. Zur ausgabe 
nicht, da kann man ausgeben bis eine 0 kommt. Zum kopieren auch nicht 
weil man bis zur 0 kopieren kann. (wenn man die maximale länge weiss)

Damit ist das nicht in jedem Fall unsinnig, warum eine Länge mitführen 
wenn sie nicht gebraucht wird.

von Bartli (Gast)


Lesenswert?

> die Frage ist für was man die länge überhaupt braucht.

Bereits für relativ triviale Stringoperationen?
1
const char *a = "irgendwas";
2
const char *b = " und sowieso";
3
char *c = malloc(strlen(a) + strlen(b) + 1);
4
/* Zusammenfuegen von a und b nach c mit strcat darfst du dir selber ausmalen. */

> Damit ist das nicht in jedem Fall unsinnig, warum eine Länge mitführen
> wenn sie nicht gebraucht wird.

Ein nullterminierter String führt implizit seine Länge mit, in Form der 
terminierenden 0, was, darauf bestehe ich, bescheuert ist.

von Bartli (Gast)


Lesenswert?

strcpy wollte ich sagen, nicht strcat.

von Karl H. (kbuchegg)


Lesenswert?

Bartli schrieb:
>> die Frage ist für was man die länge überhaupt braucht.
>
> Bereits für relativ triviale Stringoperationen?

Die du jetzt so konstruiert hast, dass man ohne Kentniss der Stringlänge 
nicht weiterkommt :-)

Aber auch du musst zugeben, dass man ohne weiteres Stringoperationen 
konstruieren kann, in denen man die Länge genau gar nicht braucht 
sondern einfach nur durch das abschliessende \0 Zeichen genug 
Information hat. Und die sind ebenfalls gar nicht mal so selten.


> Ein nullterminierter String führt implizit seine Länge mit, in Form der
> terminierenden 0, was, darauf bestehe ich, bescheuert ist.

Und ich bestehe darauf, dass das explizite Mitführen einer Länge 
bescheuert ist. :-) Wie groß machst du denn diese Längenangabe? 1 Byte, 
2 Byte, n Byte? Mit der 0-terminierung kann ein String so groß werden, 
wie es ein Pointer und der Speicher hergibt. Mit einer expliziten Länge 
hast du eine künstliche Beschränkung eingezogen.

So what?

Für jede Designentscheidung gibt es immer Dinge die dafür und Dinge die 
dagegen sprechen. Nur muss man sich halt für irgendwas entscheiden. Und 
da Arrays (bzw. allgemeiner Speicherallokierungen) in C nicht wissen wie 
groß sie sind, macht es auch keinen Sinn, für Strings da jetzt was 
anderes einzufordern.

von Bartli (Gast)


Lesenswert?

> Wie groß machst du denn diese Längenangabe? 1 Byte, 2 Byte, n Byte?
> Mit der 0-terminierung kann ein String so groß werden, wie es ein
> Pointer und der Speicher hergibt.

Du gibst die Antwort fast selber (und weisst sie natürlich auch): 
Natürlich nimmst du sinnvollerweise als Längenangabe size_t o.Ä. und 
nicht 8 Bit wie Pascal.

(Ich höre bereits das Geschrei von wegen Speicherverschwendung bei 
kleinen Strings etc:)

von Klaus W. (mfgkw)


Lesenswert?

was spricht dagegen, in den paar Fällen, wo die Länge sinnvoll ist, sie 
getrennt mitzuführen (als Länge oder als Zeiger auf das Ende)?

Wenn ich lange Strings zusammenfüge, kann ich doch das Ende mit einem 
Pointer verfolgen, der z.B. auch mit dem Rückgabewert von sprintf() 
weiter gesetzt werden kann.

Haben alle Strings zwangsweise die Länge, kann ich sie nicht mehr 
weglassen, wo sie nur Ballast ist.
C ist halt kein Pascal o.ä., wozu also krampfhaft dazu vergewaltigen?

von Karl H. (kbuchegg)


Lesenswert?

Bartli schrieb:

> Du gibst die Antwort fast selber (und weisst sie natürlich auch):

Klar weiß ich sie.

> (Ich höre bereits das Geschrei von wegen Speicherverschwendung bei
> kleinen Strings etc:)

Wenns nur das wäre.
Nehmen wir mal eine andere Funktion her

void toUpperS( char * str )
{
  while( *str )
    *str = toupper( *str++ );
}

das lässt sich wunderbar mit minimalem Registerverbrauch in Object-Code 
übersetzen. Das jewilige Zeichen muss sowieso in ein Register gelesen 
werden. Die Abfrage fürs Schleifenende tut nicht mehr besonders weh. Ist 
einfach nur ein conditional branch an geeigneter Stelle.

void toUpperS( string * str )
{
  size_t len = Slen( str );
  size_t i;

  for( i = 0; i < len; ++i )
    str[i] = toupper( str[i] );
}

kann weit nicht so effizient umgewandelt werden. Ich brauch mindestens 1
zusätzliches Register für entweder die Schleifenvariable oder für den 
Endwert des Pointers (wenn der Compiler die Indexbenutzung wegoptimiert)

von Udo S. (urschmitt)


Lesenswert?

Bartli schrieb:
> (Ich höre bereits das Geschrei von wegen Speicherverschwendung bei
> kleinen Strings etc:)

Ja und, dann nimmt man Integer mit variabler Länge. Codierung ähnlich 
wie UTF-8 man hat pro Byte 7 Nutzbit das hüchstwertige Bit gibt an daß 
das nächste Byte noch zur Länge dazugehört.
Und die, die jetzt meckern wollen das braucht zuviel Rechenzeit um die 
Länge wieder zusammenzusetzen sind genau diejenigen deren Programme auf 
einem modernen Quadcore langsamer laufen als unsere damals auf einem 
8088.

von Patrick (Gast)


Lesenswert?

Bartli schrieb:
> Natürlich nimmst du sinnvollerweise als Längenangabe size_t o.Ä.

Ja, macht Sinn; in C sind ja auch Sachen wie z. B. int 
plattformabhängig; da kommt es auf den Stringlängenindikator auch nicht 
mehr an...

Interchangeability lebe hoch!

</sarcasm>

von Bartli (Gast)


Lesenswert?

> Ja, macht Sinn; in C sind ja auch Sachen wie z. B. int
> plattformabhängig; da kommt es auf den Stringlängenindikator auch nicht
> mehr an...

Tatsächlich tut es das nicht. Wenn du dich von deinen Sarkasmusanfall 
erholt hast, schaust du dir dann z.B. auch mal an, was der Typ von 
strlen's Rückgabewert ist.

von Bartli (Gast)


Lesenswert?

> Wenns nur das wäre.
> Nehmen wir mal eine andere Funktion her

Du magst mit diesem Beispiel recht haben, gehst aber wieder davon aus 
dass man mit Strings so oder so nichts anderes tut als über die Zeichen 
zu iterieren.

von Karl H. (kbuchegg)


Lesenswert?

Bartli schrieb:
>> Wenns nur das wäre.
>> Nehmen wir mal eine andere Funktion her
>
> Du magst mit diesem Beispiel recht haben, gehst aber wieder davon aus
> dass man mit Strings so oder so nichts anderes tut als über die Zeichen
> zu iterieren.

... so wie du davon ausgegangen bist, dass man die Länge des Strings als 
Ganzes braucht :-)

Ich glaube ich sagte schon: Es hat alles sein für und wieder.

von superstru (Gast)


Lesenswert?

huhu,
muss mich korrigieren..

meine aussage weiter oben war falsch, hatte vor einiger zeit diesen 
artikel gelesen:
http://queue.acm.org/detail.cfm?id=2010365

in dem artikel geht es um vermutungen welcher der "teuerste 1-byte-bug" 
ist. nul-terminierte strings ist ein kandidat davon..

mit dicker diskussion auf slashdot:
http://developers.slashdot.org/story/11/08/03/011244/the-most-expensive-one-byte-mistake
dort bin ich auch drüber gestolpert.

von Clemens M. (panko)


Lesenswert?

Für mich war immer klar, daß man für z.B. rechtsbündiges schreiben von 
Strings deren Länge braucht, um entsprechend weit links zu beginnen. Und 
selbst wenn ich grafikmäßig von rechts nach links schriebe, muss ich 
doch dann auch das letzte Zeichen kennen, um da anzufangen.
Ich glaube Karl Heinz hat die notwendige Erfahrung um sagen zu können, 
daß die Stringlänge nicht wichtig ist, daher interessiert mich, wie du 
z.B. Text rechtsbündig hinschreibst ohne strlen - vielleicht habe ich da 
immer viel zu viel Zeit vergeudet.

von Peter D. (peda)


Lesenswert?

Clemens M. schrieb:
> daher interessiert mich, wie du
> z.B. Text rechtsbündig hinschreibst ohne strlen

"strlen" gibt es, weil man manchmal eben die Länge braucht.
Man muß sie aber nicht ständig mitführen.

Schon unter DOS wurde ein Text bis zum Endezeichen $ ausgegeben.


Peter

von Clemens M. (panko)


Lesenswert?

Die Frage war in keinster Weise provokativ gemeint.

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Effizienz ist kein gutes Argument. Die Frage ob Stringverarbeitung 
überhaupt nennenswert zur Ausführungszeit beiträgt mal außen vor 
gelassen: das byteweise Abklappern bis zur Endmarkierung mag auf dem AVR 
effizient sein, nicht aber auf aktuellen Prozessoren die gerne mit 
mindestens 32 oder 64 Bit pro Operation arbeiten. Relevant könnte das 
sein für Hash-Berechnung z.B. in Datenbanken. Und für die Darstellung im 
GUI, Schreiben in eine Datenbank, praktisch immer muss man sowieso die 
Länge wissen bevor man anfangen kann etwas zu tun.

von Andreas D. (rackandboneman)


Lesenswert?

"Datenbank, GUI..."

Nicht wirklich Bereiche in denen man auf Anwendungsebene C nehmen sollte 
:)

"Die Frage ob Stringverarbeitung überhaupt nennenswert zur 
Ausführungszeit"

Naja, wenn man XML usw ins Spiel bringt sieht es wieder ganz anders 
aus...

von Karl H. (kbuchegg)


Lesenswert?

> Ich glaube Karl Heinz hat die notwendige Erfahrung um sagen
> zu können, daß die Stringlänge nicht wichtig ist,

Holla. Das ist falsch rüber gekommen.
Ich wollte damit nicht aussagen, dass sie überhaupt nicht wichtig ist. 
Ich seh aber auch, dass oft Funktionen unnötigerweise zuerst die 
Stringlänge bestimmen, obwohl die eigentlich keiner braucht, wenn man 
nur das Verfahren umstellt.

Zu guter Letzt:
niemand hindert einen daran sich selbst eine entsprechende struct in C 
zu machen, die am Anfang ein Längenbyte besitzt. Man muss sich dann eben 
ein paar Stringhilfsfunktionen als Ersatz für die str... Funktionen 
machen, aber so viele sind das dann ja auch wieder nicht.

von wer-wie-was (Gast)


Lesenswert?

Andreas Schwarz schrieb:
> Effizienz ist kein gutes Argument. Die Frage ob Stringverarbeitung
> überhaupt nennenswert zur Ausführungszeit beiträgt mal außen vor
> gelassen: das byteweise Abklappern bis zur Endmarkierung mag auf dem AVR
> effizient sein, nicht aber auf aktuellen Prozessoren die gerne mit
> mindestens 32 oder 64 Bit pro Operation arbeiten. Relevant könnte das
> sein für Hash-Berechnung z.B. in Datenbanken. Und für die Darstellung im
> GUI, Schreiben in eine Datenbank, praktisch immer muss man sowieso die
> Länge wissen bevor man anfangen kann etwas zu tun.

Effizienz ist kein Argument? Was denn dann? Dann können ja sämtliche 
Anwendungen als interpretierte JAVA-Skripte laufen lassen, das reicht ja 
vom Zeitverhalten aus. Handoptimierte Interruptroutinen? Nicht nötig, 
nehmen wir einfach einen schnelleren Prozessor ;-)

Die Nullterminierung von C-Strings stammt aus der EDV-Urzeit und machte 
damals wegen der geringen Speichergrößen zumindestens noch etwas Sinn. 
Nach heutigen Maßstäben bzw. für aktuelle Anwendungen ist das Ganze 
etwas unglücklich. Gerade wenn ein von extern kommender String auch das 
Zeichen 0 enthalten kann!

von Yalu X. (yalu) (Moderator)


Lesenswert?

Ich sehe die C-eigene Stringdarstellung trotz einiger Nachteile nicht
als Probelm an:

Es gibt viele unterschiedliche Möglichkeiten der Repräsentation von
Strings, von denen jede ihre Vor- und Nachteile hat. Da C als schlanke
Sprache konzipiert ist, haben sich Ritchie & Co wahrscheinlich gesagt,
sie nehmen für die Stringrepräsentation einfach eine der einfachsten.

Die allereinfachste wäre die aus Fortran gewesen: Dort sind Strings
Character-Arrays ohne Längeninformation und ohne Endmarker. Ist das
Wort, das man in eine Stringvariable schreiben möchte, kürzer als die
Länge des Arrays, füllt man den Rest üblicherweise mit Leerzeichen auf.
Das ist natürlich sehr unbefriedigend, weil es damit keine Möglichkeit
gibt, zwischen Strings unterschiedlicher Länge zu unterscheiden. Ein
Vorteil besteht aber neben dem minimalen Speicherverbrauch darin, dass
man keinen speziellen Stringdatentyp braucht.

Die zweiteinfachste Möglichkeit ist ein Character-Array mit Endmarker,
was letztendlich in C implementiert worden ist. Die Vorteile sind die
gleichen wie bei der Fortran-Lösung, wobei zusätzlich die Stringlänge
variabel ist. Viele, aber nicht alle Stringoperationen lassen sich damit
halbwegs effizient implementieren.

Eine Repräsentation mit Längeninformation wie bspw. in Pascal wäre eine
in einigen Fällen effizientere Alternative gewesen, hätte aber einen
zusätzlichen Datentyp erfordert. Und auch Strings mit Längeninformation
sind nicht der Weisheit letzter Schluss, denn Operationen wie das
Einfügen oder Löschen von Zeichen in einem String sind immer noch
aufwendig.

In Textverarbeitungsanwendungen ist das Einfügen und Löschen von Zeichen
in sehr langen Texten eine wichtige Operation. Deswegen wird man denn
Text weder als Fortran- noch al C- noch als Pascal-String anlegen, son-
dern als doppelt verkettete Liste aus relativ kleinen Textfragmenten.
Dadurch geht zwar die direkte Indizierbarkeit einzelner Zeichen verlo-
ren, was aber bei diesen Anwendungen auch kaum gebraucht wird. Wenn
doch, kann man immer noch einen zusätzlichen Index anlegen.

Generell kann man sagen, dass fast überall, wo zeitkritisch große Text-
mengen bearbeitet werden müssen (also bspw. auch in Datenbanksystemen),
sowieso eine für die entsprechende Anwendung optimierte Textdarstellung
verwendet wird. Für alle nicht zeitkritischen Fälle (wie bspw. Benutzer-
ein-/ausgabe) ist die interne Darstellung ziemlich egal, so dass man
diejenige nimmt, die von der eingesetzten Programmiersprache nativ
unterstützt wird. In C sind das eben die nullterminierten Character-
Arrays, die in meinen Augen ganz gut in die C-Philosphie passen.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Bartli schrieb:
>> die Frage ist für was man die länge überhaupt braucht.
>
> Bereits für relativ triviale Stringoperationen?
1
> const char *a = "irgendwas";
2
> const char *b = " und sowieso";
3
> char *c = malloc(strlen(a) + strlen(b) + 1);
4
> /* Zusammenfuegen von a und b nach c mit strcat darfst du dir selber
5
> ausmalen. */

Und wie würdest du das hinschreiben, wenn die Strings nicht 
0-terminiert wären sondern die Länge mitführten?

Nicht viel anders, wohl.

Ich hab deinen Code mal durch einen "realen C Compiler" gelassen
1
#include <string.h>
2
#include <stdlib.h>
3
4
char* foo (void)
5
{
6
    const char *a = "irgendwas";
7
    const char *b = " und sowieso";
8
    char *c = malloc (strlen(a) + strlen(b) + 1);
9
    return c;
10
}

avr-gcc sagt:
1
foo:
2
  ldi r24,lo8(22)
3
  clr r25
4
  jmp malloc

>> Damit ist das nicht in jedem Fall unsinnig, warum eine Länge mitführen
>> wenn sie nicht gebraucht wird.
>
> Ein nullterminierter String führt implizit seine Länge mit, in Form der
> terminierenden 0, was, darauf bestehe ich, bescheuert ist.

Ich sag mal so: Es ist angehehmen, einen Punkt am Ende eines Satzes zu 
machen, als am Anfang des Satzes hinzuschreiben, wie lange er ist :o)

Selbst du machst nen Punkt am Satzende.

von Bartli (Gast)


Lesenswert?

Ach komm, jetzt stellst du dich doof an. Dir sollte ja eigentlich 
schon klar sein dass ein gescheiter Compiler solche Codeschnippsel 
komplett zusammenfalten kann: In diesem Fall kennt er den Inhalt der 
Strings und strlen() ist anscheinend eine Builtinfunktion. Wenn du etwas 
messen willst musst du schon was komplexeres hernehmen :P

von Rolf M. (rmagnus)


Lesenswert?

Johann L. schrieb:
> Ich sag mal so: Es ist angehehmen, einen Punkt am Ende eines Satzes zu
> machen, als am Anfang des Satzes hinzuschreiben, wie lange er ist :o)

Und? Deshalb muß das für einen Computer nicht automatisch auch ideal 
sein.

Johann L. schrieb:
> Und wie würdest du das hinschreiben, wenn die Strings nicht
> 0-terminiert wären sondern die Länge mitführten?
>
> Nicht viel anders, wohl.

Anders hinschreiben nicht, aber die Operation, die in strlen() 
ausgeführt wird, wäre eine andere.

Johann L. schrieb:
> #include <string.h>
> #include <stdlib.h>
>
> char* foo (void)
> {
>     const char *a = "irgendwas";
>     const char *b = " und sowieso";
>     char *c = malloc (strlen(a) + strlen(b) + 1);
>     return c;
> }

Dann versuch mal einen Fall, in dem die Stringinhalte an der Stelle 
nicht schon dem Compiler bekannt sind:
1
#include <string.h>
2
#include <stdlib.h>
3
4
char* foo (const char* a, const char* b)
5
{
6
    char *c = malloc (strlen(a) + strlen(b) + 1);
7
    return c;
8
}

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Das ist freilich ein komplett anderer Code.

Mit dem ursprünglichen Code ist es wie mit mindestens 50% aller 
Codebeispiele, die ein Problem oder "Bug" demonstrieren sollen: Der Code 
ist Märchencode und das Problem versteckt sich im 
Pünktchen-Pünktchen-Pünktchen.

von Rolf M. (rmagnus)


Lesenswert?

Johann L. schrieb:
> Das ist freilich ein komplett anderer Code.
>
> Mit dem ursprünglichen Code ist es wie mit mindestens 50% aller
> Codebeispiele, die ein Problem oder "Bug" demonstrieren sollen: Der Code
> ist Märchencode und das Problem versteckt sich im
> Pünktchen-Pünktchen-Pünktchen.

Märchencode ist vor allem deiner. Wann kommt es in der Realität schon 
vor, daß ich zwei Strings zusammensetzen will, die ich beide direkt 
davor im Code wörtlich stehen habe? Warum ist es nicht gleich ein 
String? Meistens wird man die Strings eben nicht zur Compilezeit schon 
kennen.
Und während die Variante mit expliziter Länge immer performant ist, ist 
es die mit der Nullterminierung nur in manchen Fällen, wo der Compiler 
halt gut optimieren kann.

von Klaus W. (mfgkw)


Lesenswert?

Rolf Magnus schrieb:
> Und während die Variante mit expliziter Länge immer performant ist

naja

Die Länge braucht irgendwo Platz (mind. 4 Byte, wenn die Strings nicht 
gleich wieder zu limitiert sein sollen), und ggf. dafür ein Register zur 
Laufzeit (oder entsprechend viele auf einem uC).

Evtl. hat man weiterhin noch je eine weitere Dereferenzierung, um an die 
Zeichen zu kommen, wenn man in einer struct o.ä. neben der Länge erst 
den Zeiger auf die eigentlichen Zeichen hat.

Bei 0-terminierten Strings braucht man nur den Zeiger auf das erste 
Zeichen, der Rest ergibt sich.

In vielen Fällen ist das performanter, in den anderen Fällen kann man 
bei Bedarf die Länge explizit mitführen.

Streiten kann man darüber, was jetzt wie häufig vorkommt - aber kann man 
kaum behaupten, daß ein pascalähnlicher String generell performanter 
wäre.

Jedenfalls würde es der ganzen Philosophie hinter C widersprechen, 
nämlich in einfachen Fällen auch einfache Lösungen zu haben, um nicht 
zwangsweise zuviele Resourcen zu verbrauchen.
Das Rundum-Wohlfühl- und Sicherheitspaket ohne Nachdenken ist C nun mal 
nicht, dafür nimmt man besser etwas anderes (wenn man es haben möchte).

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Rolf Magnus schrieb:
> Johann L. schrieb:
>> Das ist freilich ein komplett anderer Code.
>>
>> Mit dem ursprünglichen Code ist es wie mit mindestens 50% aller
>> Codebeispiele, die ein Problem oder "Bug" demonstrieren sollen: Der Code
>> ist Märchencode und das Problem versteckt sich im
>> Pünktchen-Pünktchen-Pünktchen.
>
> Märchencode ist vor allem deiner.

Hallo? Das ist der Code von

Beitrag "Re: Strings ohne Null am Ende?"

allerdings so geschrieben, daß er compilierbar ist.


> Wann kommt es in der Realität schon
> vor, daß ich zwei Strings zusammensetzen will, die ich beide direkt
> davor im Code wörtlich stehen habe?

Guckst du zB in den Quellen von avr-gcc

http://gcc.gnu.org/viewcvs/trunk/gcc/config/avr/avr.c?content-type=text%2Fplain&view=co

nach dem Makro STR_PREFIX_P sowie der inline-Funktion avr_replace_prefix 
und wie sie verwendet werden.

Ich behaupte jetzt mal: GCC-Quellen sind kein Märchen-Code ;-)

> Und während die Variante mit expliziter Länge immer performant ist, ist
> es die mit der Nullterminierung nur in manchen Fällen, wo der Compiler
> halt gut optimieren kann.

Es ist nun mal so in C. Du kannst ebensogut darüber disputieren, ob 
Hamburg nicht besser an der Elbe gebaut worden wäre.  Ist es aber nun 
mal nicht. Jeder, der sich mit C auskennt, weiß auch um die Nachteile 
und Macken der Sprache.

Brian Kernighan: "It seemed like a good idea at the time."

von Klaus W. (mfgkw)


Lesenswert?

Johann L. schrieb:
> ob
> Hamburg nicht besser an der Elbe gebaut worden wäre.  Ist es aber nun
> mal nicht.

wäre aber bestimmt eine tolle Idee: leichter Zugang zur Nordsee, schicke 
Wohngegend am Elbufer, nette Museumsschiffe, Landungsbrücken...

Aber ohne Elbe ist es vielleicht doch besser - kein Pieselwetter, nicht 
so viele lästige Brücken und keine stinkenden Schiffe.
Das haben sie damals bestimmt richtig gemacht!

von Bartli (Gast)


Lesenswert?

>Hallo? Das ist der Code von
>Beitrag "Re: Strings ohne Null am Ende?"
>allerdings so geschrieben, daß er compilierbar ist.

Ja, der ist ursprünglich von mir, und du hast in aus dem Kontext 
gerissen, durch einen Compiler gejagt und damit irgendwas beweisen 
wollen.

von Werner (Gast)


Lesenswert?

Das Blöde an der Stringverarbeitung von C ist, dass sie schon scheitert, 
wenn man damit einen 8-Bit Datenstrom von einer seriellen Schnittstelle 
verarbeiten möchte.

von Rolf M. (rmagnus)


Lesenswert?

Werner schrieb:
> Das Blöde an der Stringverarbeitung von C ist, dass sie schon scheitert,
> wenn man damit einen 8-Bit Datenstrom von einer seriellen Schnittstelle
> verarbeiten möchte.

Was verstehst du unter "8-Bit  Datenstrom"? Wenn du damit Daten meinst, 
die eben keine Strings sind, dann sollte dafür auch keine 
Stringverarbeitung zum Einsatz kommen.

Johann L. schrieb:
> Ich behaupte jetzt mal: GCC-Quellen sind kein Märchen-Code ;-)

Ich will ja gar nicht sagen, daß es nie vorkommt, sondern nur daß es 
nicht gerade der Standardfall ist.

>> Und während die Variante mit expliziter Länge immer performant ist, ist
>> es die mit der Nullterminierung nur in manchen Fällen, wo der Compiler
>> halt gut optimieren kann.
>
> Es ist nun mal so in C. Du kannst ebensogut darüber disputieren, ob
> Hamburg nicht besser an der Elbe gebaut worden wäre.  Ist es aber nun
> mal nicht. Jeder, der sich mit C auskennt, weiß auch um die Nachteile
> und Macken der Sprache.

Ich dachte, daß wir darüber diskutieren, ob nullterminierte Strings 
besser sind oder schlechter als welche mit Längenangabe und nicht 
darüber, ob C geändert werden sollte.

von Werner (Gast)


Lesenswert?

Rolf Magnus schrieb:
> Was verstehst du unter "8-Bit  Datenstrom"? Wenn du damit Daten meinst,
> die eben keine Strings sind, dann sollte dafür auch keine
> Stringverarbeitung zum Einsatz kommen.
Irgendwelche Zeichenfolgen, die in 8-Bit Paketen daherkommen. Wo siehst 
du den Unterschied von Zeichen und Daten?


> Ich dachte, daß wir darüber diskutieren, ob nullterminierte Strings
> besser sind oder schlechter als welche mit Längenangabe und nicht
> darüber, ob C geändert werden sollte.

Nullterminierte Strings scheitern schon bei 8-Bit Zeichen. Was für ein 
Anchronismus aus den Zeiten der frühen Datenübertragung.

von Klaus W. (mfgkw)


Lesenswert?

Beliebige Daten können Nullbytes enthalten, Textdaten nicht.

Wer nullterminierte Strings für beliebige Daten mißbraucht ist selbst 
schuld.

Anachronismus ist, nicht dazu lernen zu wollen.

von Rolf M. (rmagnus)


Lesenswert?

Werner schrieb:
> Rolf Magnus schrieb:
>> Was verstehst du unter "8-Bit  Datenstrom"? Wenn du damit Daten meinst,
>> die eben keine Strings sind, dann sollte dafür auch keine
>> Stringverarbeitung zum Einsatz kommen.
> Irgendwelche Zeichenfolgen, die in 8-Bit Paketen daherkommen. Wo siehst
> du den Unterschied von Zeichen und Daten?


Daten werden so wie sie sind verarbeitet. Bei Text ist das eben nicht 
der Fall. In C ist das mit den 0-Bytes noch am simpelsten. Bei anderen 
Sprachen müßtest du beim Einlesen erstmal ein Character Set angeben, und 
alles wird dann für die interne Darstellung erstmal nach UTF8 oder gar 
in einen 16-Bit-Zeichensatz konvertiert. Aber auch in C gibt's bei Files 
z.B. einen Text- und einen Binary-Modus, und wenn man den Textmodus 
nutzt, werden systemspezifische Konvertierungen beim Lesen vorgenommen.

>> Ich dachte, daß wir darüber diskutieren, ob nullterminierte Strings
>> besser sind oder schlechter als welche mit Längenangabe und nicht
>> darüber, ob C geändert werden sollte.
>
> Nullterminierte Strings scheitern schon bei 8-Bit Zeichen. Was für ein
> Anchronismus aus den Zeiten der frühen Datenübertragung.

Welcher 8-Bit-Zeichensatz würde dir denn einfallen, bei dem das nicht 
funktioniert?

Beitrag #7509587 wurde von einem Moderator gelöscht.
Beitrag #7509604 wurde von einem Moderator gelöscht.
Beitrag #7509610 wurde von einem Moderator gelöscht.
Beitrag #7509634 wurde von einem Moderator gelöscht.
Dieser Beitrag ist gesperrt und kann nicht beantwortet werden.