Forum: PC-Programmierung [C] Namensgebung von 'strchr' oder 'memchr'


von Danish B. (danishbelal)


Lesenswert?

Guten Tag,

weiß jemand warum die Funktionen 'strcrh()' und 'memchr()' diese 'chr' 
im Namen tragen?

Die Funktionen suchen in einem String nach dem Vorkommen eines Zeichens, 
erfüllen also eine Suchfunktion.
Ich kann mir diese Namen nicht erklären.


BTW: Bin mir nicht sicher, ob das in PC-Programmierung oder eher nach OT 
gehört. Bei Bedarf bitte verschieben.

von Bitwurschtler (Gast)


Lesenswert?

char (enl.) ... Zeichen

von Bitwurschtler (Gast)


Lesenswert?

Grmpf, character  ... Zeichen,

von Joachim B. (jar)


Lesenswert?

ich weiss auch nicht warum man arrays of char String nennt, aber da es 
nun mal so ist finde ich strchr also char in str(ing) suchen passend,

str der String chr das char.

von Danish B. (danishbelal)


Lesenswert?

Danke für die Antworten.

Da sah ich doch glatt den Wald vor lauter Bäumen nicht mehr :).

Schönen Tag noch.

von C. A. Rotwang (Gast)


Lesenswert?

Joachim B. schrieb:
> ich weiss auch nicht warum man arrays of char String nennt, aber da es
> nun mal so ist finde ich strchr also char in str(ing) suchen passend,
>
> str der String chr das char.

Hat man sich möglischlerweise ausgedacht um C wie ne "Hochsprache" mit 
"abstrakten" Datentypen aussehen zu lassen. IMHO wäre es besser gewesen 
die Dinge als das zu bezeichnen was diese aus Sicht der CPU sind: Byte 
und Block aus Byte.

Zum darstellbaren Zeichen "wird" das Byte erste durch weitere Hardware 
(tty, Grafikadapter, Zeichengenerator). Ein Zusammenhang zu 
Nachbar-Bytes in Form einer Kette ist auch nicht gegebebn, die Bytes 
können weitgehend beliebig angeordnet werden. Und spätestens seit UTF 
ASCII als Standard-Zeichensatz ablöste ist die Beschränkung auf 8bit 
Breite für ein Zeichen obsolete.

IMHO hätten es Anfänger leichter wenn C ehrlich zu seiner Herkunft aus 
der Assemblerprogrammierung stehen würde.

von Rolf M. (rmagnus)


Lesenswert?

C. A. Rotwang schrieb:
> Hat man sich möglischlerweise ausgedacht um C wie ne "Hochsprache" mit
> "abstrakten" Datentypen aussehen zu lassen.

Ich denke, es kommt eher daher, dass zu der Zeit, als C erfunden wurde, 
ein Byte und ein Zeichen mehr oder weniger als das selbe angesehen 
wurden. Letztendlich war das Byte damals über zwei Eigenschaften 
definiert:

- Die kleinste einzeln adressierbare Einheit des Systems
- Die Speichermenge, die nötig ist, um ein Zeichen des
  Systemzeichensatzes zu speichern

Und nach der Art ist es in C bis heute definiert.

> IMHO wäre es besser gewesen die Dinge als das zu bezeichnen was diese aus
> Sicht der CPU sind: Byte und Block aus Byte.

Es wäre im Nachhinein gesehen zumindest besser gewesen, Datentypen für 
Text und für 1-Byte-Integer verschieden zu nennen und auch die 
Konvertierung zwischen ihnen explizit zu machen (wie z.B. in Pascal mit 
der Funktion CHR, die einen Integer in ein Zeichen wandelt).

> Zum darstellbaren Zeichen "wird" das Byte erste durch weitere Hardware
> (tty, Grafikadapter, Zeichengenerator).

Eigentlich wird es dazu durch die Interpretation der Daten. Ein Byte ist 
genau genommen zunächst mal nur ein Zusammenschluss von mehreren Bits, 
die jeweils zwei mögliche Zustände haben können. Ob man das jetzt z.B. 
als Dualzahlzahl mit dem Dezimal-Wert 34, das Anführungszeichen oder den 
errno-Wert ERANGE sieht, ist einzig Sache der Interpretation. Selbst die 
Bedeutung der einzelnen Bits sind schon Interpretation, also ob sie nun 
0 und 1, true und false, rechts und links oder an und aus bedeuten.

> Ein Zusammenhang zu Nachbar-Bytes in Form einer Kette ist auch nicht
> gegebebn, die Bytes können weitgehend beliebig angeordnet werden.

Wenn ich einen Satz in einem String speichere und die Buchstaben dann 
alphabetisch sortiere, kommt nicht viel sinnvolles dabei raus, also 
spielt die Reihenfolge wohl durchaus eine Rolle, wenn auch nicht auf 
Ebene der Sprache selbst (bis auf die Tatsache, dass ein '\0' das Ende 
markiert).

> Und spätestens seit UTF ASCII als Standard-Zeichensatz ablöste ist die
> Beschränkung auf 8bit Breite für ein Zeichen obsolete.

Ja.

: Bearbeitet durch User
von C. A. Rotwang (Gast)


Lesenswert?

Rolf M. schrieb:
> C. A. Rotwang schrieb:
>> Hat man sich möglischlerweise ausgedacht um C wie ne "Hochsprache" mit
>> "abstrakten" Datentypen aussehen zu lassen.
>
> Ich denke, es kommt eher daher, dass zu der Zeit, als C erfunden wurde,
> ein Byte und ein Zeichen mehr oder weniger als das selbe angesehen
> wurden. Letztendlich war das Byte damals über zwei Eigenschaften
> definiert:
>
> - Die kleinste einzeln adressierbare Einheit des Systems
> - Die Speichermenge, die nötig ist, um ein Zeichen des
>   Systemzeichensatzes zu speichern

Sicher?
Die PDP-11 als erste Maschine die wohl  in C-programmiert wurde hat 
16bit, die PDP-9 dagegen 12. Und der selber Prozesser/Rechenwerk kann in 
verschiedene Systeme verbaut unterschiedlich breite Daten ansteuern 
(8/16bit Speicherbus, 8/16 ISA - 32bit PCI-bus, ARM-Thumb modi, 
386SX/DX, ...)

char ist wohl eher als element eines Strings angedacht gewesen und beide 
als abstrakte Datentaypen im gegensatz zu den "maschinendatentypen" 
integer und array.
Die besonderheit von String ist IMHO das es ohne Index auskommt ,aber 
dafür ein Terminierungszeichen benötigt. So ein Terminiriungszeichen 
benögt man aber vornehmlich bei der Kommunikation über Terminals (End of 
line/Transmission) nicht aber bei skalierbaren Speicher. Deshalb passt 
es m.E. nicht, wenn mensch bei Suchen/Operationen über Speicherbereiche 
von strings spricht. Vielleicht wird ja strcpy() irgendwann von dem 
passenderen memcpy() ersetzt, dann würden auch viele Sicherheitslücken 
entschärft.

von Dirk B. (dirkb2)


Lesenswert?

C. A. Rotwang schrieb:
> Vielleicht wird ja strcpy() irgendwann von dem
> passenderen memcpy() ersetzt, dann würden auch viele Sicherheitslücken
> entschärft.

Die Sicherheitslücke kommt daher, dass nicht überprüft wird, ob im 
Zielbereich genug Platz ist.
Das passiert bei memcpy auch nicht.

Also muss sich der Programmierer selber darum kümmern, aber das kann er 
auch bei strcpy.

von C. A. Rotwang (Gast)


Lesenswert?

Dirk B. schrieb:
> C. A. Rotwang schrieb:
>> Vielleicht wird ja strcpy() irgendwann von dem
>> passenderen memcpy() ersetzt, dann würden auch viele Sicherheitslücken
>> entschärft.
>
> Die Sicherheitslücke kommt daher, dass nicht überprüft wird, ob im
> Zielbereich genug Platz ist.
> Das passiert bei memcpy auch nicht.
>
> Also muss sich der Programmierer selber darum kümmern, aber das kann er
> auch bei strcpy.

Hm ist da nicht strncpy statt strcpy die Lösung? Und noch besser der 
völlige Verzicht auf Transfer mit "implititer Längensteuerung" 
(Terminirungscode), so das man sozusagen "gezwungen wird" eine 
maximallänge für die Operation vorzugeben und daher immer den 
Speicherbedarf für den Zielbereich "im Hinterkopf" hat?

von Rolf M. (rmagnus)


Lesenswert?

C. A. Rotwang schrieb:
>> Ich denke, es kommt eher daher, dass zu der Zeit, als C erfunden wurde,
>> ein Byte und ein Zeichen mehr oder weniger als das selbe angesehen
>> wurden. Letztendlich war das Byte damals über zwei Eigenschaften
>> definiert:
>>
>> - Die kleinste einzeln adressierbare Einheit des Systems
>> - Die Speichermenge, die nötig ist, um ein Zeichen des
>>   Systemzeichensatzes zu speichern
>
> Sicher?
> Die PDP-11 als erste Maschine die wohl  in C-programmiert wurde hat
> 16bit, die PDP-9 dagegen 12.

Ja, und? Dass das Byte je als "fix 8 Bit" definiert wäre, ist ein 
Mythos. Tatsächlich waren Bytes, als das Wort erfunden wurde, nur 5 oder 
6 Bit lang.
Dazu kommt noch, dass ein C-Byte nicht zwingend einem Byte der Hardware 
entsprechen muss. C definiert eine abstrakte Maschine, und der Compiler 
darf das auf Ebene dieser abstrakten Maschine durchaus anders definieren 
als das, was die Hardware zur Verfügung stellt.
Übrigens: Sowohl 12, als auch 16 Bit große Bytes sind in C erlaubt. Nur 
weniger als 8 Bit sind nicht erlaubt. Das heißt, auf einem 4-Bit-System 
(was es im µC-Bereich ja gibt) müsste der Compiler zwei Prozessor-Bytes 
zu einem C-Byte zusammenfassen.

> Und der selber Prozesser/Rechenwerk kann in verschiedene Systeme verbaut
> unterschiedlich breite Daten ansteuern (8/16bit Speicherbus, 8/16 ISA -
> 32bit PCI-bus, ARM-Thumb modi, 386SX/DX, ...)

Aber die kleinste Speichermenge, die man auf einmal lesen oder schreiben 
kann ist immer ein Byte. Ich spreche hier von den Instruktionen, die der 
Prozessor zur Verfügung stellt, nicht davon, was dann auf dem 
Speicherbus passiert. Das ist bei modernen Prozessoren sowieso viel 
komplizierter mit Multicore, virtueller Speicherverwalung und 
mehrstufigen Cache-Systemen.

> char ist wohl eher als element eines Strings angedacht gewesen

char schon, aber es gibt ja auch noch signed char und unsigned char.

von Rolf M. (rmagnus)


Lesenswert?

Hier noch die Definition von "Byte" in der C-Norm:

byte
addressable unit of data storage large enough to hold any member of the 
basic character set of the execution environment
NOTE 1 It is possible to express the address of each individual byte of 
an object uniquely.

von S. R. (svenska)


Lesenswert?

C. A. Rotwang schrieb:
> IMHO wäre es besser gewesen die Dinge als das zu bezeichnen
> was diese aus Sicht der CPU sind: Byte und Block aus Byte.

C unterscheidet immerhin konsistent zwischen "String" (Byte-Array mit 
Nullterminierung, str*-Funktionen) und "Bytestring" (Byte-Array ohne 
Nullterminierung, mem*-Funktionen). Mit Multibyte-Texten hatten die 
Erfinder nicht gerechnet. :-)

Rolf M. schrieb:
> Übrigens: Sowohl 12, als auch 16 Bit große Bytes sind in C erlaubt.

Allerdings nicht in POSIX, wo implizit erzwungen wird, dass ein Byte 
exakt 8 Bit hat. Das schränkt die Nützlichkeit dann doch stark ein (gibt 
es überhaupt einen C-Compiler, der "char" nicht mit 8 Bits definiert?)

von tictactoe (Gast)


Lesenswert?

S. R. schrieb:
> (gibt
> es überhaupt einen C-Compiler, der "char" nicht mit 8 Bits definiert?)

Ich glaube schon, mal sowas gehört zu haben. Es ist nämlich so, dass 
C/C++ verlangt, dass das gleichzeitige Manipulieren von 
aneinandergrenzenden char-Objekten kein Data-Race mit sich bringen darf. 
Jetzt gibt es aber CPUs, die ein Byte nur ändern können, indem sie ein 
Maschinenwort von 16 oder 32 Bits lesen, das Byte ändern und dann wieder 
das ganze Wort schreiben. Das zwingt dazu, dass char 16 oder 32 Bits 
breit ist, obwohl ein Byte nach wie vor 8 Bits hat.

von (prx) A. K. (prx)


Lesenswert?

Wobei es damals Maschinen gab, bei denen die Zeichendarstellung reine 
Konvention war. Wenn die Maschine Worte adressierte und der Befehlssatz 
keine besonderen Präferenzen für die Verarbeitung von Zeichen hatte. 
Dann konnte es von der Programmiersprache abhängen, ob ein Zeichen in 6 
Bits codiert wurde, was für wissenschaftliche Aufgaben völlig 
ausreichte, oder in 8 Bits, wenn Klein/Grossschreibung relevant war.

von S. R. (svenska)


Lesenswert?

Dann würde ich aber nicht erwarten, dass der Compiler "char" mit 16 Bit 
definiert, sondern dass er einfach Padding-Bytes einfügt. Die Elemente 
eines Arrays zählen m.W. nicht als getrennte Objekte, deine Feststellung 
dürfte also nur für das Array als Ganzes zählen.

Ein char mit abweichender Bitbreite würde so ziemlich jeden 
existierenden Code kaputtmachen (inklusive der existierenden libcs), 
dass ich mir das allerhöchstens auf irgendwelchen seltsamen 
DSP-Architekturen vorstellen kann.

Aber da hätte ich gerne ein Beispiel für, ehe ich das glaube.

von (prx) A. K. (prx)


Lesenswert?

tictactoe schrieb:
> Das zwingt dazu, dass char 16 oder 32 Bits
> breit ist, obwohl ein Byte nach wie vor 8 Bits hat.

Geht nicht. Ein char ist ein Byte gross. Ein Byte darf aber mehr als 8 
Bits haben.

"The sizeof operator yields the size (in bytes) of its operand,"

"When sizeof is applied to an operand that has type char, unsigned char, 
or signed char, (or a qualified version thereof) the result is 1."

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

S. R. schrieb:
> Ein char mit abweichender Bitbreite würde so ziemlich jeden
> existierenden Code kaputtmachen (inklusive der existierenden libcs),

Weshalb POSIX das Byte auf 8 Bits festnagelt. Nicht aber C.

> Aber da hätte ich gerne ein Beispiel für, ehe ich das glaube.

Wie du schon sagst, diverse DSPs, wie etwa die C54x.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

tictactoe schrieb:
> C/C++ verlangt, dass das gleichzeitige Manipulieren von
> aneinandergrenzenden char-Objekten kein Data-Race mit sich bringen darf.

Wo?

von (prx) A. K. (prx)


Lesenswert?

Rolf M. schrieb:
> NOTE 1 It is possible to express the address of each individual byte of
> an object uniquely.

Prinzipiell sollte es möglich sein, auch rein wortadressierende 
Maschinen mit 8-Bit Bytes auszustatten. Nur wären die Adressen davon 
dann nicht mehr direkt von der Hardware nutzbar, sondern eine Art 
Bitfeld aus Wortadresse und Byte im Wort mit etwas umständlichem Code 
für den Zugriff. Was dann eine unterschiedliche Darstellung von Pointern 
auf Bytes und Worte zu Folge hätte und bei Cast-Ketten recht lustig 
werden könnte.

Umgekehrt ist es auch nicht korrekt, ein Byte als kleinste adressierbare 
Einheit zu definieren, wie es oft zu lesen ist. Der Speicher darf auch 
bitadressiert arbeiten, aber weil ein Byte mindestens 8 Bits hat, müssen 
dann 8 zusammen kommen.

Zu realen Maschinen aus diesem Jahrtausend: Dallas/Maxims MaxQ2000 ist 
eine 16-Bit Maschine, die Bytes mit Byteadressen und Worte mit 
Wortadressen adressiert. Worte in der zweiten RAM-Hälfte sind nicht 
byteweise adressierbar, weil dafür 17 Bits nötig wären. Umwandlung 
zwischen char- und int-Pointern sind also nicht einfach nur eine Sache 
der Interpretation, sondern Rechenarbeit.

von (prx) A. K. (prx)


Lesenswert?

tictactoe schrieb:
> Jetzt gibt es aber CPUs, die ein Byte nur ändern können, indem sie ein
> Maschinenwort von 16 oder 32 Bits lesen, das Byte ändern und dann wieder
> das ganze Wort schreiben. Das zwingt dazu, dass char 16 oder 32 Bits
> breit ist, obwohl ein Byte nach wie vor 8 Bits hat.

DEC Alpha adressierte zwar Bytes, hatte aber in der ersten Generation 
noch keine Lade/Speicher-Befehle für 8- und 16-Bit Objekte. Das hat 
niemanden daran gehindert, in C mit 8 Bit Bytes/chars zu arbeiten. Das 
war bloss umständlicher im Code, weshalb ab der zweiten Generation 
entsprechende Befehle hinzu kamen.

von tictactoe (Gast)


Lesenswert?

A. K. schrieb:
> tictactoe schrieb:
>> C/C++ verlangt, dass das gleichzeitige Manipulieren von
>> aneinandergrenzenden char-Objekten kein Data-Race mit sich bringen darf.
>
> Wo?

Für C++: §4.4p3 (von Working Draft N4659):

>  A memory location is [...] an object of scalar type [...]. Two or more threads 
of execution (4.7) can access separate memory locations without interfering with 
each other.

von Jobst Q. (joquis)


Lesenswert?

C. A. Rotwang schrieb:
> Hm ist da nicht strncpy statt strcpy die Lösung?

strncpy ist die schlechteste Lösung, da es entgegen jeder Erwartung 
nicht einen String als String kopiert, sondern einen String in einen 
mem-block.

Wenn n erreicht wird, wird kein Stringende (Nullbyte) kopiert, womit der 
Zielstring eine Länge bekommt bis zur nächsten zufälligen Null, was in 
den seltensten Fällen vom Programmierer beabsichtigt ist. Vom Hacker 
vielleicht schon.

Meine Funktion zum begrenzten kopieren:
https://www.mikrocontroller.net/topic/goto_post/4862280

> Und noch besser der
> völlige Verzicht auf Transfer mit "implititer Längensteuerung"
> (Terminirungscode), so das man sozusagen "gezwungen wird" eine
> maximallänge für die Operation vorzugeben und daher immer den
> Speicherbedarf für den Zielbereich "im Hinterkopf" hat?

Niemand zwingt dich in C, die nullterminierte Stringbearbeitung zu 
verwenden, wenn du damit nicht klarkommst. Du kannst alles auch mit 
mem-Funktionen erledigen, es ist nur bedeutend aufwendiger.

Wer Probleme hat, Zweiradfahren zu lernen, darf auch weiterhin gerne ein 
Dreirad benutzen. Wer aber fordert, dass alle Fahrzeuge mindestens 3 
Räder haben müssen, damit mehr Leute gezwungen werden Dreirad zu fahren, 
muss mit berechtigtem Widerstand von Zweiradfahrern rechnen, die die 
Vorzüge von Zweirädern kennen.

von (prx) A. K. (prx)


Lesenswert?

tictactoe schrieb:
> Für C++: §4.4p3 (von Working Draft N4659):

Danke. Das gilt soweit ich erkennen kann aber erst seit C++ 11.
Nicht davor, und auch nicht in C.

: Bearbeitet durch User
von Nop (Gast)


Lesenswert?

Jobst Q. schrieb:

> Wenn n erreicht wird, wird kein Stringende (Nullbyte) kopiert

Weswegen ich bei strncpy danach nochmal etwas wie dest_str[LEN-1]=0 
mache, wobei LEN die Buffergröße ist. Genauso übrigens auch, wenn ich 
mit fgets zeilenweise von einem Stream lese.

> Niemand zwingt dich in C, die nullterminierte Stringbearbeitung zu
> verwenden, wenn du damit nicht klarkommst. Du kannst alles auch mit
> mem-Funktionen erledigen, es ist nur bedeutend aufwendiger.

Hauptnachteil von Pascal-artigen Strings (also mit expliziter 
Längenangabe) ist, daß man nicht einfach mit einem Pointer im String 
durchlaufen kann und trotzdem immer einen gültigen Reststring behält. 
Auch das Anhängen von Strings an andere ist etwas aufwendiger als nötig.

Andererseits ist strcat auch einfach nur schlecht umgesetzt, weil das 
einen Pointer auf den Ergebnisstring zurückliefert, den man aber nicht 
braucht, weil man den dest-Pointer ja schon als Funktionsparameter 
mitgibt. Was man haben will, ist vielmehr der Pointer auf das 
Stringende, wo man dann direkt den nächsten String dransetzen kann, ohne 
vorher den ganzen String von vorne auf der Suche nach der Null zu 
durchlaufen.

Da hat man schon die Daten, die einen als Returnwert interessieren, aber 
man gibt lieber einen nutzlosen Wert zurück. Die Konsequenz ist, daß man 
strcat praktisch nicht gebrauchen kann, wenn man mehr als einmal was 
anhängt.

Was passiert, wenn man strcat dafür doch nutzt, sieht man z.B. bei 
schlechten Datei-Explorern, wenn man ein Verzeichnis mit tausenden 
Dateien öffnet. Zusammen mit n^2-Sortieralgorithmen einer der 
beliebtesten Fallstricke, wobei strcat bei dieser Nutzung ja n^2 ist.

von (prx) A. K. (prx)


Lesenswert?

A. K. schrieb:
> Danke. Das gilt soweit ich erkennen kann aber erst seit C++ 11.
> Nicht davor, und auch nicht in C.

... vor Version 11.

Das ist insofern interessant, als es bestimmte Hardware-Eigenschaften 
erzwingt. Die sind zwar heute ziemlich verbreitet, aber es ist für C 
recht ungewöhnlich, in neuen Standards in dieser Form alte Zöpfe 
abzuschneiden.

: Bearbeitet durch User
von Nop (Gast)


Lesenswert?

tictactoe schrieb:

> Das zwingt dazu, dass char 16 oder 32 Bits
> breit ist, obwohl ein Byte nach wie vor 8 Bits hat.

Andererseits ist sizeof(char) als 1 definiert. Es ist aber nirgends 
gesagt, daß die Einheit dieser 1 Bytes sein muß, aber zusammen damit, 
daß nur char-Pointer überhaupt beliebig aliasen dürfen und char 
eigentlich immer 1 Byte ist, sehe ich da ein großartiges Potential, daß 
ganze Codebasen zerbrechen.

Oder ist die Lösung dafür ganz einfach, daß man auf Hardware, die Bytes 
nicht atomar schreiben kann, kein C11 verwenden sollte?

von (prx) A. K. (prx)


Lesenswert?

Nop schrieb:
> Oder ist die Lösung dafür ganz einfach, daß man auf Hardware, die Bytes
> nicht atomar schreiben kann, kein C11 verwenden sollte?

Zumindest wird es bei solcher Hardware keinen vollständig konformen 
11er Compiler geben, der 8-Bit Bytes als Grunddatentyp unterstützt.

Dort wo es solche Architekturen heute gibt, dürfte eine optionale nicht 
konforme Unterstützung solcher Bytes allerdings keine grossen Proteste 
auslösen. Und man kämpft beim Compiler wahrscheinlich immer noch mit der 
vollständigen Umsetzung von C99. ;-)

: Bearbeitet durch User
von PittyJ (Gast)


Lesenswert?

Schaut euch einfach mal die Signal-Prozessoren der 28xx Reihe von TI an.

http://www.ti.com/product/sm320f2812-ep?keyMatch=2812&tisearch=Search-EN-Everything

Dort hat eine Speicherzelle 16 Bit.
sizeof(char) == sizeof(short) == sizeof(int) == 1, alles 16 Bit.
Speichert man wirklich nur 8 Bit Zeichen, dann sind die obersten 8 Bit 
verschwendet.
Man kann auch im Speicher kein Byte alleine ansprechen, sondern immer 
nur eine Speicherzelle zu 16 Bit lesen.

Die C-Compiler entsprechen alle den Standards, da sind keine 
Verrenkungen nötig.

Soviel dazu, dass es nur in der Vergangenheit ungewöhnliche Bitbreiten 
gab. Der Prozessor ist aktuell, und ich hab den für ein Projekt benutzt.

von Dirk B. (dirkb2)


Lesenswert?

C. A. Rotwang schrieb:
> Hm ist da nicht strncpy statt strcpy die Lösung?

strncpy setzt nicht die '\0', wenn die angegebene Länge erreicht wird.
Der String ist dann nicht mehr terminiert.


> Und noch besser der
> völlige Verzicht auf Transfer mit "implititer Längensteuerung"
> (Terminirungscode), so das man sozusagen "gezwungen wird" eine
> maximallänge für die Operation vorzugeben und daher immer den
> Speicherbedarf für den Zielbereich "im Hinterkopf" hat?

Dann musst du immer zwei Längen mit dir rum schleppen. Die maximale 
Länge und die belegte Länge.

Die Angabe der Größe eines Speicherbereichs sollte man aber (beim 
schreiben) immer mit angeben, solange sie nicht trivial ist.

von Jobst Q. (joquis)


Lesenswert?

Dirk B. schrieb:
> Die Angabe der Größe eines Speicherbereichs sollte man aber (beim
> schreiben) immer mit angeben, solange sie nicht trivial ist.

Besser noch wäre die Grenze des Speicherbereichs als Pointer zu merken 
und als Parameter in den Schreibfunktionen festzulegen. Denn diese 
Grenze muss nur einmal berechnet werden (lim= buf +sizeof(buf);)und 
bleibt gleich bei allen Vorgängen auf diesen Bereich, während die Größe 
des verbliebenen Speichers immer wieder neu berechnet werden muss.

Die Standard-Stringfunktionen sind leider mehr Größen- als 
Pointerorientiert. Aber auch dort ist eine lim-Variable hilfreich:

t+= snprintf( t,lim-t,...);

kann beliebig kaskadiert werden, wenn man von den Ungereimtheiten des 
Rückgabewerts von snprintf mal absieht.

von mh (Gast)


Lesenswert?

A. K. schrieb:
> A. K. schrieb:
>> Danke. Das gilt soweit ich erkennen kann aber erst seit C++ 11.
>> Nicht davor, und auch nicht in C.
>
> ... vor Version 11.
>
> Das ist insofern interessant, als es bestimmte Hardware-Eigenschaften
> erzwingt. Die sind zwar heute ziemlich verbreitet, aber es ist für C
> recht ungewöhnlich, in neuen Standards in dieser Form alte Zöpfe
> abzuschneiden.

Solange der Zugriff auf ein CPU-Byte auf CPU-Ebende atomar ist, sollte 
keine Änderung am Compiler oder am Program nötig sein.

von S. R. (svenska)


Lesenswert?

PittyJ schrieb:
> Schaut euch einfach mal die Signal-Prozessoren
> der 28xx Reihe von TI an.
>
> Soviel dazu, dass es nur in der Vergangenheit ungewöhnliche Bitbreiten
> gab. Der Prozessor ist aktuell, und ich hab den für ein Projekt benutzt.

Danke für den Hinweis.

> Die C-Compiler entsprechen alle den Standards, da sind keine
> Verrenkungen nötig.

Nur POSIX kannst du damit halt nicht machen, was auf nem DSP aber auch 
nicht sooo wichtig ist. :-)

von (prx) A. K. (prx)


Lesenswert?

mh schrieb:
>> Das ist insofern interessant, als es bestimmte Hardware-Eigenschaften
>> erzwingt. Die sind zwar heute ziemlich verbreitet, aber es ist für C
>> recht ungewöhnlich, in neuen Standards in dieser Form alte Zöpfe
>> abzuschneiden.
>
> Solange der Zugriff auf ein CPU-Byte auf CPU-Ebende atomar ist, sollte
> keine Änderung am Compiler oder am Program nötig sein.

Eben dies ist der Punkt. C/C++ 11 ist mit 8-Bit Bytes nur 
implementierbar, wenn die Hardware darauf atomar zugreifen kann. Das 
scheint mir bei allen aktuellen CPUs auch der Fall zu sein, bei denen 
POSIX eine Rolle spielt (bei DSPs dürfte das kaum interessieren). Aber 
das ist eben eine neue Forderung, die CPUs wie die erste 
Alpha-Generation faktisch ausgeschlossen hätte.

: Bearbeitet durch User
von S. R. (svenska)


Lesenswert?

A. K. schrieb:
> Aber das ist eben eine neue Forderung, die CPUs wie die erste
> Alpha-Generation faktisch ausgeschlossen hätte.

Was aber auch daran liegt, dass neue Anforderungen - wie z.B. 
Multithreading - hinzugekommen sind, von echt-paralleler Verarbeitung 
nicht zu reden. Die erste Alpha-Generation konnte auch das nicht.

von (prx) A. K. (prx)


Lesenswert?

S. R. schrieb:
> Was aber auch daran liegt, dass neue Anforderungen - wie z.B.
> Multithreading - hinzugekommen sind, von echt-paralleler Verarbeitung
> nicht zu reden. Die erste Alpha-Generation konnte auch das nicht.

Multithreading als Arbeitsweise von Prozessen gab es damals bereits, 
mehrere Prozessoren ebenfalls. Auch auf diesen Alphas. Nur parallele 
Threads innerhalb eines Cores noch nicht (SMT, Hyperthreading).

: Bearbeitet durch User
von Nop (Gast)


Lesenswert?

S. R. schrieb:

> Was aber auch daran liegt, dass neue Anforderungen - wie z.B.
> Multithreading - hinzugekommen sind

Interrupts kannte so ziemlich jede CPU, und das ist in dieser Hinsicht 
auch nicht anders.

von (prx) A. K. (prx)


Lesenswert?

Nop schrieb:
> Interrupts kannte so ziemlich jede CPU, und das ist in dieser Hinsicht
> auch nicht anders.

Mit C/C++ 11 wurde Multithreading in die Standards aufgenommen. Davor 
war Multithreading darin nicht berücksichtigt. Diese Anforderung an das 
Speichermodell ist eine direkte Folge davon.

von Cyblord -. (cyblord)


Lesenswert?

C. A. Rotwang schrieb:
> Hat man sich möglischlerweise ausgedacht um C wie ne "Hochsprache" mit
> "abstrakten" Datentypen aussehen zu lassen. IMHO wäre es besser gewesen
> die Dinge als das zu bezeichnen was diese aus Sicht der CPU sind: Byte
> und Block aus Byte.

Humbug. Am Ende ist immer alles im Speicher nur ein Byte oder ein 
Byteblock. Also Unsinn. Eine double ist auch nur eine Reihe von Bytes. 
Diese Bytes haben einen Datentyp, damit das System weiß wie die Daten zu 
interpretieren sind. Und auch die Ausgabe kann dadurch angepasst werden.
Also char ist da keine spezielle Ausnahme.

von S. R. (svenska)


Lesenswert?

A. K. schrieb:
> Multithreading als Arbeitsweise von Prozessen gab es damals bereits,
> mehrere Prozessoren ebenfalls. Auch auf diesen Alphas.

Meines Wissens ist die schlecht definierte (= kaputte) Speichersemantik 
vor C11 genau diesen ersten Alphas geschuldet, weil deren Hardware da 
mangelhaft ist. Gibt es einen guten Vortrag von Herb Sutter zu modernem 
C++ dazu ("Atomic<> Weapons").

Multithreading ist auf diesen Prozessoren kein Problem, solange man bloß 
nicht versucht, moderne (lock-free) Algorithmen anzuwenden. Vor 20 
Jahren war das nur ein Randthema (der Linux-Source enthält genau 
deswegen noch immer ziemlich abartige Atomics, v.a. für Treiber), 
inzwischen ist es auch in normalen Anwendungen üblich.

Sowohl Interrupts als auch Multitasking waren auf den Alphas nie ein 
Problem, weil dort immer ein vollständiger Kontextwechsel stattfindet.

von (prx) A. K. (prx)


Lesenswert?

S. R. schrieb:
> Sowohl Interrupts als auch Multitasking waren auf den Alphas nie ein
> Problem, weil dort immer ein vollständiger Kontextwechsel stattfindet.

Es gab für diese Alphas auch Windows NT, und damit Threads mit 
gemeinsamem Speicherkontext.

: Bearbeitet durch User
von S. R. (svenska)


Lesenswert?

Ja, und Windows NT nutzt keine lockfree-Algorithmen zur Synchronisierung 
von Threads - auch kein Problem.

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.