Frage

Da mit und ohne Vorzeichen Ints die gleichen Register, etc. verwenden, und nur Bitmuster unterschiedlich interpretieren und C Zeichen sind im Grunde nur 8-Bit ints, was ist der Unterschied zwischen mit und ohne Vorzeichen Zeichen in C? Ich verstehe, dass die Signedness Saiblings ist Implementierung definiert, und ich kann einfach nicht verstehen, wie es überhaupt einen Unterschied machen könnte, zumindest wenn char verwendet Strings zu halten statt Mathematik zu tun.

War es hilfreich?

Lösung

Es wird kein Unterschied für Streicher machen. Aber in C können Sie ein Zeichen verwenden, Mathematik zu tun, wenn es einen Unterschied machen.

In der Tat, wenn in eingeschränkten Speicherumgebungen, wie eingebettete 8-Bit-Anwendungen ein Zeichen arbeitet, wird häufig verwendet werden, Mathematik zu tun, und dann macht es einen großen Unterschied. Dies ist, weil es kein byte Typ standardmäßig in C ist.

Andere Tipps

In Bezug auf die Werte, die sie darstellen:

unsigned char:

  • erstreckt sich der Wertebereich 0..255 (00000000..11111111)
  • Werte Überlauf rund um niedrige Kante als:

    0 - 1 = 255 (00000000 - 00000001 = 11111111)

  • Werte Überlauf rund um hohe Kanten als:

    255 + 1 = 0 (11111111 + 00000001 = 00000000)

  • bitweise Verschiebung nach rechts Operator (>>) hat eine logische Verschiebung:

    10000000 >> 1 = 01000000 (128 / 2 = 64)

signed char:

  • erstreckt sich der Wertebereich -128..127 (10000000..01111111)
  • Werte Überlauf rund um niedrige Kante als:

    -128 - 1 = 127 (10000000 - 00000001 = 01111111)

  • Werte Überlauf rund um hohe Kanten als:

    127 + 1 = -128 (01111111 + 00000001 = 10000000)

  • bitweise Verschiebung nach rechts Operator (>>) hat eine arithmetische Verschiebung:

    10000000 >> 1 = 11000000 (-128 / 2 = -64)

I der die binären Darstellungen zu zeigen, dass das Wert Wickelverhalten rein, konsistente binäre Arithmetik und hat nichts mit einem Zeichen zu tun ist, mit / ohne Vorzeichen (erwarten für Rechtsverschiebungen).

Aktualisieren

Einige implementierungsspezifisches Verhalten in den Kommentaren erwähnt:

#include <stdio.h>

int main(int argc, char** argv)
{
    char a = 'A';
    char b = 0xFF;
    signed char sa = 'A';
    signed char sb = 0xFF;
    unsigned char ua = 'A';
    unsigned char ub = 0xFF;
    printf("a > b: %s\n", a > b ? "true" : "false");
    printf("sa > sb: %s\n", sa > sb ? "true" : "false");
    printf("ua > ub: %s\n", ua > ub ? "true" : "false");
    return 0;
}


[root]# ./a.out
a > b: true
sa > sb: true
ua > ub: false

Es ist wichtig, wenn Strings zu sortieren.

Es gibt ein paar Unterschiede. Am wichtigsten ist, wenn Sie den gültigen Bereich eines char Überlauf durch eine zu große oder kleine ganze Zahl zuweisen und Zeichen signiert sind, ist der resultierende Wert Implementierung definiert oder sogar einige Signale (in C) gestiegen ist, wie für alle signierten Typen werden könnte . Vergleichen Sie das mit dem Fall, wenn Sie etwas zu groß oder klein zu einem unsigned char zuordnen: der Wert umschlingt, werden Sie genau Semantik definiert. Zum Beispiel wird eine -1 auf ein unsigned char zuweisen, erhalten Sie eine UCHAR_MAX bekommen. Also, wenn Sie ein Byte wie in einer Zahl von 0 bis 2 ^ CHAR_BIT haben, sollten Sie wirklich unsigned char verwenden zu speichern.

Das Zeichen macht auch einen Unterschied, wenn sie Vararg Funktionen übergeben:

char c = getSomeCharacter(); // returns 0..255
printf("%d\n", c);

Angenommen, die auf c zugewiesenen Wert wäre zu groß für char darzustellen, und die Maschine verwendet Zweier-Komplement. Viele Implementierung verhalten sich für den Fall, dass Sie einen zu großen Wert auf die Zeichen zuweisen, dass die Bit-Muster wird sich nicht ändern. Wenn ein int alle Werte von char darzustellen in der Lage, (was es für die meisten Implementierungen ist), dann wird das Zeichen wird, bevor er zu printf in int gefördert. So ist der Wert dessen, was passiert ist, wäre negativ. Förderung behalten würde int dieses Zeichen. So werden Sie ein negatives Ergebnis. Wenn jedoch unsigned char ist, dann ist der Wert ohne Vorzeichen, und in einem int Förderung eine positive int ergeben. Sie können unsigned char verwenden, dann werden Sie genau definiertes Verhalten sowohl für die Zuweisung auf die Variable, und vorbei an printf, die dann positiv etwas gedruckt wird.

Beachten Sie, dass ein Zeichen, unsigned und signed char alle sind mindestens 8 Bit breit. Es gibt keine Anforderung, dass char ist genau 8 Bit breit. Doch für die meisten Systeme, die stimmt, aber für einige, werden Sie sie verwenden 32-Bit-Zeichen finden. Ein Byte in C und C ++ definiert die Größe der Zeichen zu haben, also ein Byte in C auch nicht immer genau 8 Bit ist.

Ein weiterer Unterschied ist, dass in C, ein unsigned char keine Füllbits haben muss. Das heißt, wenn Sie feststellen, CHAR_BIT 8 ist, dann ist ein unsigned char Werte müssen im Bereich von 0 .. 2 ^ CHAR_BIT-1. Das gleiche gilt für char wenn es unsigned ist. Für signed char, können Sie nichts über den Bereich von Werten annehmen, auch wenn Sie wissen, wie Ihr Compiler das Zeichen Zeug (Zweier-Komplement oder die anderen Optionen) implementiert, kann es nicht verwendete Paddingbits darin. In C ++ gibt es keine Füllbits für alle drei Charaktertypen.

  
    

„Was bedeutet es für ein Zeichen unterzeichnet werden?“

  

Traditionell besteht der ASCII-Zeichensatz von 7-Bit-Zeichenkodierungen. (Im Gegensatz zu den 8-Bit-EBCIDIC.)

Wenn die C-Sprache entwickelt und umgesetzt wurde dies ein wichtiges Thema war. (Aus verschiedenen Gründen wie die Datenübertragung über serielle Modem-Geräte.) Das zusätzliche Bit hat verwendet wie Parität.

A „unterzeichnet Zeichen“ geschieht für diese Darstellung perfekt sein.

Binärdaten OTOH, einfach den Wert jedes 8-Bit „Brocken“ von Daten nehmen, damit kein Zeichen benötigt wird.

Arithmetik auf Bytes ist wichtig für die Computergrafik (wobei 8-Bit-Werte häufig verwendet werden, Farben zu speichern). Abgesehen davon, kann ich mir vorstellen zwei Fälle, in denen char Zeichen Sachen:

  • auf eine größere int Umwandlung
  • Vergleichsfunktionen

Die böse Sache ist, diese werden Sie nicht beißen, wenn alle Ihre String-Daten sind 7-Bit. Aber es verspricht, eine unerschöpfliche Quelle von obskurer Bugs zu sein, wenn Sie versuchen, Ihr C / C ++ Programm 8-Bit-sauber.

machen

Signedness funktioniert so ziemlich die gleiche Art und Weise in chars wie es in anderen ganzzahligen Typen der Fall ist. Wie Sie bemerkt haben, Zeichen sind wirklich nur ein Byte ganze Zahlen. ( Nicht unbedingt 8-Bit , obwohl Es gibt einen Unterschied;!. Ein Byte sein könnte größer als 8 Bit auf einigen Plattformen und chars sind eher gebunden an Bytes aufgrund der Definitionen von char und sizeof(char) Die CHAR_BIT Makro, in <limits.h> oder C ++ 's <climits> definiert, werden Sie sagen, wie viele Bits in einem char sind.).

Was, warum Sie ein Zeichen mit einem Zeichen wollen würden: in C und C ++ gibt es keinen Standard-Typen namens byte. Um die Compiler, chars ist Bytes und umgekehrt, und es unterscheidet nicht zwischen ihnen. Manchmal aber wollen Sie - manchmal Sie , dass char sein, um eine Ein-Byte-Zahl, und in diesen Fällen (vor allem, wie klein einen Bereich ein Byte haben kann), können Sie auch in der Regel egal, ob die Zahl ist signiert oder nicht. Ich habe persönlich Signedness (oder unsignedness) pflegte zu sagen, dass eine bestimmte char ein (numerisch) „Byte“ und nicht als ein Zeichen, und dass es wird numerisch verwendet werden. Ohne Angabe Signedness, ist, dass char wirklich ein Zeichen, und sollte als Text verwendet werden.

Früher habe ich das zu tun, eher. Nun sind die neueren Versionen von C und C ++ (u?)int_least8_t haben (derzeit typedef'd in <stdint.h> oder <cstdint>), die mehr explizit numerisch sind (obwohl sie werden in der Regel nur typedefs für signierte und unsignierte char Typen sowieso).

Die einzige Situation, kann ich mir vorstellen das ein Problem sein, wenn Sie auf Zeichen tun Mathe wählen. Es ist vollkommen legal den folgenden Code zu schreiben.

char a = (char)42;
char b = (char)120;
char c = a + b;

Je nach Signedness der Kohle könnte c eine von zwei Werten sein. Wenn Chars nicht signiert sind, dann wird c (char) 162 sein. Wenn sie angemeldet sind, dann wird es ein Überlauf Fall als Maximalwert für ein signed char ist 128. Ich vermute, die meisten Implementierungen zurückkehren würde nur (char) -32.

Eine Sache, über unterzeichneten Zeichen ist, dass Sie c> = ‚testen‘ (Leerzeichen) und sicher sein, es ist ein normales druckbaren ASCII-Zeichen. Natürlich ist es nicht tragbar, so nicht sehr nützlich.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top