Ich habe festgestellt, dass der C99-Standard eine Anweisung hat, die die Kompatibilität zwischen dem Typ char und dem Typ signed char / unsigned char verweigert.
Hinweis 35 des C99-Standards:
CHAR_MIN, definiert in limits.h, wird einen der Werte 0 oder SCHAR_MIN haben, und dies kann verwendet werden, um die zwei Optionen zu unterscheiden. Unabhängig von der getroffenen Wahl ist char ein separater Typ von den anderen beiden und ist nicht kompatibel mit beiden.
Meine Frage ist, warum verweigert das Komitee die Kompatibilität? Was ist der Grund? Wenn char mit einem signierten Char oder unsigned char kompatibel ist, wird etwas schreckliches passieren?
Die Wurzeln sind in der Compiler-Geschichte. Es gab (waren) im Wesentlichen zwei C-Dialekte in den Achtzigern:
Welche von diesen sollte C89 standardisiert haben? C89 hat sich dafür entschieden, keines zu standardisieren, da es eine große Anzahl von Annahmen in bereits geschriebenem C-Code ungültig gemacht hätte - welche Standard-Leute die installierte Basis nennen. Also hat C89 getan, was K & R getan hat: die Signedness von plain char implementation-defined lassen. Wenn Sie eine bestimmte Signedness benötigen, qualifizieren Sie Ihren Char.
Bei modernen Compilern können Sie den Dialekt normalerweise mit einer Option auswählen (z. B. gcc's -funsigned-char
).
Die "schreckliche" Sache, die passieren kann, wenn Sie den Unterschied zwischen (un) signiertem char und normalem char ignorieren, ist, dass Sie Zeichenerweiterungen erhalten, wenn Sie nicht arithmetisch arbeiten und ohne diese Details berücksichtigen erwarte sie oder umgekehrt (oder sogar undefiniertes Verhalten beim Verschieben).
Es gibt auch einige dumme Ratschläge, die empfehlen, Ihre Zeichen immer mit einem expliziten, signierten oder unsignierten Qualifier zu deklarieren. Dies funktioniert so lange, wie Sie nur mit Zeigern auf solche qualifizierten Typen arbeiten, aber erfordert hässliche Umwandlungen, sobald Sie sich mit Strings und String-Funktionen beschäftigen, die alle mit Zeiger-zu-Zeichen-Zeichen arbeiten , die ohne Besetzung ohne Zuweisung ist. Ein solcher Code wird plötzlich mit Tonnen von hässlichen Knochensätzen verputzt.
Die Grundregeln für Zeichen sind:
char
für Strings und wenn Sie Zeiger auf Funktionen übergeben müssen, die plain char unsigned char
, wenn Sie Bit-Twiddling und das Verschieben von Bytes signed char
, wenn Sie kleine signierte Werte benötigen, aber denken Sie daran, int
zu verwenden, wenn der Platz keine Rolle spielt Denken Sie an signed char
und unsigned char
als die kleinsten arithmetischen, integralen Typen, genau wie signed short
/ unsigned short
und so weiter mit int
, long int
, long long int
. Diese Typen sind alle genau spezifiziert.
Andererseits dient char
einem ganz anderen Zweck: Es ist der grundlegende Typ von I / O und die Kommunikation mit dem System. Es ist nicht für Berechnungen gedacht, sondern als Einheit von Daten . Deshalb finden Sie char
in den Befehlszeilenargumenten, in der Definition von "Strings", in den FILE*
-Funktionen und in anderen IO-Funktionen vom Typ Lesen / Schreiben sowie in der Ausnahme der strengen Aliasing-Regel. Dieser char
-Typ ist absichtlich weniger streng definiert, damit jede Implementierung die "natürlichste" Darstellung verwenden kann.
Es ist einfach eine Frage der Trennung von Verantwortlichkeiten.
(Allerdings ist char
layoutkompatibel mit signed char
und unsigned char
, sodass Sie die eine explizit in die andere und zurück konvertieren können.)
Tags und Links c char compatibility