Warum ist char nicht kompatibel mit signed char oder unsigned char?

8

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?

    
junwanghe 07.10.2012, 14:06
quelle

2 Antworten

9

Die Wurzeln sind in der Compiler-Geschichte. Es gab (waren) im Wesentlichen zwei C-Dialekte in den Achtzigern:

  1. Wo einfache Zeichen signiert sind
  2. Wo einfaches Zeichen unsigned ist

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:

  • Verwenden Sie plain char für Strings und wenn Sie Zeiger auf Funktionen übergeben müssen, die plain char
  • verwenden
  • Verwenden Sie unsigned char , wenn Sie Bit-Twiddling und das Verschieben von Bytes
  • durchführen müssen
  • Verwenden Sie signed char , wenn Sie kleine signierte Werte benötigen, aber denken Sie daran, int zu verwenden, wenn der Platz keine Rolle spielt
Jens 07.10.2012 14:18
quelle
2

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.)

    
Kerrek SB 07.10.2012 14:12
quelle

Tags und Links