Somit scheint der unterschied zwischen char und byte nur noch
das vorzeichen zu sein.
Ich möchte nun ein Zeichen aus einer ASCII Tabelle abspeichern,
was macht es hier fuer einen sinn CHAR zu verwenden und somit ein
Vorzeichen+
zu haben? -127 bis +127 deckt alle 127 ASCII zeichen doch schon ab.
und ein BYTE ist so gesehen auch nicht größer, es können nur mehr Zahlen
dargestellt
werden weil ebend das sign bit fehlt.
Kann da jemand klarheit rein bringen?
Ein char muss nicht 8bit sein. Wenn du eine 8bit-Zahl willst verwende
(u)int8_t . "char" kann signed sein, muss aber nicht. unsigned char und
signed char können beide gleich viele Zeichen darstellen (nämlich
2^CHAR_BITS).
Ja aber bleiben wir doch nur mal bei den 3 Typen.
UCHAR8 und BYTE sind das selbe, haben nur andere namen.
Wo ist den nun der magische unterschied zwischen.
"unsigned char" und "char" bzw ebend signed char.
Es gibt also zwei
+-127
und 0-254
Wenn ich hier rein Zahlen speichern will, ist alles klar.
Nur wenn ich hier rein zeichen Unterbringen möchte, worin unterscheiden
sich dann die zwei?
Simon schrieb:> Es gibt also zwei> +-127> und 0-254
Falsch. Falls CHAR_BITS=8 ist (zB auf x86 oder AVR oder ARM) geht
signed char von -128 bis 127, und unsigned char von 0 bis 255. Beides
mal 256 Möglichkeiten. "char" ist entweder äquivalent zu "signed char"
oder zu "unsigned char", abhängig vom Compiler.
Simon schrieb:> Nur wenn ich hier rein zeichen Unterbringen möchte, worin unterscheiden> sich dann die zwei?
Was verstehst du unter "Zeichen"? C-String-Literale müssen immer in
"char" gespeichert werden.
Hi, Simon,
> Wo ist den nun der magische unterschied zwischen.> "unsigned char" und "char" bzw ebend signed char.
In nicht so überarbeiteten Momenten, scheint mir, (oder einem anderen
unter
Deinem Nick) war Dir das schon klar: Die "Magie" ist die Fehlermeldung
Deines Compilers, wenn Dein Code den type "BIRNE" in type "Aepfel"
wandeln will.
Ciao
Wolfgang Horn
Simon schrieb:> Wo ist den nun der magische unterschied zwischen.>> "unsigned char" und "char" bzw ebend signed char.
Bei einem char ist nicht geregelt ob er ein Vorzeichen hat oder nicht.
Welches der Fall ist entscheidet der COmpiler bzw. der Compilerbauer, je
nachdem, was auf der entsprechenden CPU einfacher ist.
Es gibt aber Fälle, in denen du es nicht dem Zufall überlassen willst,
ob ein char ein Vorzeichen hat oder nicht. Zb immer dann, wenn du
tatsächlich damit rechnen willst. Bei reiner Textverarbeitung (im
Bereich des ASCII Codes) ist das hingegen wurscht. Für Textverarbeitung
nimmst du char und der Compiler darf sich aussuchen, ob für ihn mit oder
ohne Vorzeichen einfacher umzusetzen ist (aber er muss dabei natürlich
konsistent sein)
Man muss in einem für einzelne Zeichen definierten Typ mit Vorzeichen
keinen tieferen Sinn suchen. Dass es das überhaupt gibt hat seine
Ursache in grauer Vorzeit, in der C in den USA in 7-Bit ASCII auf einer
Maschine implementiert wurde, die Bytes mit Vorzeichen leichter
verarbeiten konnte als ohne.
Seither muss die Welt mit diesem Unsinn leben, ob sie will oder nicht.
Und so ist für den Typ "char" per C Definition nicht festgelegt, ob mit
oder ohne Vorzeichen. Und da "char *" und "unsigned char *" zwei paar
Stiefel und Strings "char *" sind, bleibt man bei Arrays aus Zeichen
eben besser bei "char".
Karl Heinz Buchegger schrieb:> Zb immer dann, wenn du> tatsächlich damit rechnen willst.
aaaah...Danke, ok gibt es dafür noch ein Beispiel?
Es gibt Leute die wandeln z.B. Ziffern 0-9 um indem sie einfach ein
0x30 (ascci Ziffer 0) hinzu addieren.
Meintest du das mit rechnen? nur das wäre sowohl bei signed als auch
unsigned machbar.
Simon schrieb:> Karl Heinz Buchegger schrieb:>> Zb immer dann, wenn du>> tatsächlich damit rechnen willst.>> aaaah...Danke, ok gibt es dafür noch ein Beispiel?
5 - 9
reicht dir das als Beispiel?
> Es gibt Leute die wandeln z.B. Ziffern 0-9 um indem sie einfach ein> 0x30 (ascci Ziffer 0) hinzu addieren.
Ja,
aber erstens handelt es sich da immer noch klar um Textverarbeitung.
Zweitens ist der ASCII Code von '0' - '9' in einem Bereich, in dem man
keine Probleme mit dem Vorzeichen kriegt und drittens ist die Addition
des ASCII Codes für '0' zu einer Konstanten im Bereich 0 bis 9 ebenfalls
harmlos und bleibt im Bereich der 7-Bit ASCII Codes.
d.h. das fällt unter die Kategorie Textverarbeitung. Genauso wie die
Umwandlung von Grossbuchstaben in Kleinbuchstaben, indem man mit dem
ASCII Code rechnet. Ja, man rechnet damit, aber es ist trotzdem noch
Textverarbeitung (Hinweis: Im Computer ist ausnahmslos alles eine Zahl
und jegeliche Manipulation eine Berechnung. Entscheidend ist hier nicht
der Vorgang das gerechnet wird, sondern mit welcher Absicht gerechnet
wird. Und die Absicht ist hier nun mal einen Text zu bearbeiten)
> Meintest du das mit rechnen?
Nein.
Eine Schleife die 5 mal wiederholt werden muss hat einen Schleifenzähler
der von 0 bis 4 läuft.
Übliche Raumtemeperaturen laufen (in unseren Breiten) von -30°C (in
Kühlhäusern) bis +99°C (in der Sauna).
Die Anzahl der Fernseher in einem Haushalt wird selten größer als 255
sein (und praktisch nie kleiner als 0)
...
Der Vollständigkeit halber wäre noch zu erwähnen, dass nach wie vor
Zeichensätze verwendet werden, in denen 'I'+1 nicht 'J' ist. In denen
die Bedingung (c >= 'A' && c <= 'Z') nicht sinnvoll ist, weil sie
beispielsweise '\\' einschliesst.
Das bedeutet für mich aber auch jedesmal casten zu müssen.
Mal ein Beispiel von Microchip
1
BOOLStringToIPAddress(BYTE*str,IP_ADDR*IPAddress)
Diese funktion verwendet doch ganz klar einen BYTE pointer, und nicht
ein char pointer fuer seinen string, somit bleibt mir doch nur die Wahl
zu casten oder ebend doch Zeichen als BYTE zu deklarieren.
A. K. schrieb:> Der Vollständigkeit halber wäre noch zu erwähnen, dass nach wie vor> Zeichensätze verwendet werden, ....
absolut.
EBCDIC (und damit IBM) lässt grüssen. (andere kenn ich nicht, ausser
noch viel proprietäreren Codierungen. Der ZX80 hatte glaub ich da was
spezielles)
Aber man muss auch sagen, dass die mittlerweile (Gott sei Dank) ein
Schattendasein fristen. Der Rest benutzt ASCII und hat damit schon
Probleme genug.
Was natürlich nichts daran ändert, dass es darüber keine Garantie aus
dem C-Standard gibt. (Wer hätte das gedacht :-))
>> Diese funktion verwendet doch ganz klar einen BYTE pointer, und nicht> ein char pointer fuer seinen string, somit bleibt mir doch nur die Wahl> zu casten oder ebend doch Zeichen als BYTE zu deklarieren.
Wo liegt das Problem?
Mit Hilfsfunktionen und/oder Makros kann und konnte man in C schon immer
die Dinge die nicht passen passend machen. Ohne den kompletten Code
wegen Castings unleserlich zu machen.
Ja, das kommt vor, dass API-Schreiber nicht mitdenken und den falschen
Typ benutzen. Aber man muss das ja nicht weiter treiben.
Das gibts ja an anderen Stellen auch:
zb Verwendung von Funktionen aus der mem...() Familie, wenn eigentlich
str...() angebracht wäre. Und auch umgekehrt: Verwendung von Funktionen
aus der str...() Familie, wenn eigentlich mem...() angebracht wäre.
itoa() benutzt, wenn es eigentlich utoa() sein sollte, und natürlich
auch umgekehrt. etc. etc.
Es gibt eben viele Stolpersteine in C. Wer eine Tante zum Lulu gehen
braucht, sollte sich eine andere Programmiersprache suchen und einen
großen Bogen um C machen.
Karl Heinz Buchegger schrieb:> Der ZX80 hatte glaub ich da was spezielles
Gezwungenermassen. Durch Z80 Prozessor und Board-Logik war vorgegeben,
dass der Code für Zeilende 0x76 sein musste und in 0x40-0x7F kein
weiterer gültiger Code liegen durfte.
> Aber man muss auch sagen, dass die mittlerweile (Gott sei Dank) ein> Schattendasein fristen. Der Rest benutzt ASCII und hat damit schon> Probleme genug.
Wobei die EBCDIC Maschinen immer noch gebaut, weiterentwickelt,
eingesetzt und u.A. in C programmiert werden. Was man vom ZX80 nicht
behaupten kann.
A. K. schrieb:> Wobei die EBCDIC Maschinen immer noch gebaut, weiterentwickelt,> eingesetzt und u.A. in C programmiert werden.
Tatsächlich? Wo, und warum?
Rufus Τ. Firefly schrieb:>> Wobei die EBCDIC Maschinen immer noch gebaut, weiterentwickelt,>> eingesetzt und u.A. in C programmiert werden.>> Tatsächlich? Wo, und warum?
IBMs System z lebt als Nachfolger von 360 und 370 weiterhin fort, auf
aktuell gehaltener technischer Basis (derzeit 5,5GHz Hexacore Chips).
Vorwiegend wohl als Basis hochverfügbarer Systeme, denn dafür werden
diese Maschinen hardwaremässig speziell konstruiert. Und die sind in
allerlei Sprachen programmierbar, darunter auch C.
Da diese Maschinen partitioniert betrieben werden, ist der in der
jeweiligen Partition verwendete Zeichensatz frei definierbar. Linux auf
System z verwendet zwar kein EBCDIC, die traditionellen Betriebssysteme
hingegen schon: http://www.ibm.com/developerworks/library/l-systemz/
Ich will das Thema ja nicht wieder aufwärmen, aber ehm:
Warum nimmt man hier char und baut daraus eine union mit BYTE. um dann
auch noch Bit zugriff zu haben?
1
union
2
{
3
struct
4
{
5
charIPAddress:1;// Leased IP address is valid
6
charGateway:1;// Gateway address is valid
7
charMask:1;// Subnet mask is valid
8
charDNS:1;// Primary DNS is valid
9
charDNS2:1;// Secondary DNS is valid
10
charHostName:1;// Host name is valid (not implemented)
Simon schrieb:> Nur warum einmal unsigned und einmal nicht, und warum überhaupt char?
"char" kann je nach Plattform negative Werte annehmen und ein Bitfeld
eines Basistyp mit Vorzeichen kann ebenfalls negative Werte annehmen.
Ein Bitfeld mit Basistyp char und 1 Bit Länge kann je nach Plattform 0/1
oder 0/-1 enthalten. Sinnvoll ist ein nacktes "char" also i.d.R. nicht.
Wenn schon, dann "signed char" oder "unsigned char".
Allerdings sind Bitfelder, die eine genau definierte Anordnung
voraussetzen, von Haus aus nur begrenzt portabel. Wer seinen Code für
genau eine Plattform schreibt, wie bei Controllern oft der Fall, der
legt nicht immer viel Wert auf solche Feinheiten.
Ob man als Basistyp "unsigned" statt "unsigned char" wählt kann je nach
Compiler oder ABI Unterschiede ergeben. Viele Plattformen behandeln ein
als "unsigned" deklariertes Bitfeld hinsichtlich Aligment wie ein
normales "unsigned".
So wird im ARM ABI die Struct
struct { unsigned i:1; }
auf 4 Bytes aligned,
struct { unsigned char i:1; }
aber nicht.