Was ist CHAR_BIT?

91

Zitieren des Codes zum Berechnen des ganzzahligen Absolutwerts (abs) ohne Verzweigung von http://graphics.stanford.edu/~seander/bithacks.html :

int v;           // we want to find the absolute value of v
unsigned int r;  // the result goes here 
int const mask = v >> sizeof(int) * CHAR_BIT - 1;

r = (v + mask) ^ mask;

Patentierte Variante:

r = (v ^ mask) - mask;

Was ist CHAR_BITund wie wird es verwendet?

dato datuashvili
quelle

Antworten:

-2

Sie sollten sich bewusst sein, dass dieser Code vom implementierungsdefinierten Verhalten der richtigen Bitverschiebung bei signierten Typen abhängt. gcc verspricht, immer das richtige Verhalten zu geben (Vorzeichen-Bit-Erweiterung), aber ISO C ermöglicht es der Implementierung, die oberen Bits mit Null zu füllen.

Ein Weg, um dieses Problem zu umgehen:

#ifdef HAVE_SIGN_EXTENDING_BITSHIFT
int const mask = v >> sizeof(int) * CHAR_BIT - 1;
#else
int const mask = -((unsigned)v >> sizeof(int) * CHAR_BIT - 1);
#endif

Ihr Makefileoder config.husw. kann HAVE_SIGN_EXTENDING_BITSHIFTabhängig von Ihrer Plattform zur Erstellungszeit definiert werden.

R .. GitHub HÖREN SIE AUF, EIS ZU HELFEN
quelle
120
Ich verstehe nicht, wie dies eine akzeptierte Antwort sein kann, da es die Frage nicht beantwortet, obwohl es ein sehr interessanter Kommentar ist.
QDII
14
@Mauris: Jemand hat die Frage bearbeitet und eine Unterfrage zum Fragentitel befördert. Der ursprüngliche Titel war zwar schrecklich, aber die Frage des OP war, wie der zitierte Bit-Hack-Code funktioniert, und "zumindest nicht portabel und hier ist der Grund" ist eine nützliche Antwort.
R .. GitHub STOP HELPING ICE
12
Oh ich verstehe. Leider taucht diese Frage in den Google-Suchergebnissen für "Was ist CHAR_BIT?" Sehr häufig auf. , auch wenn das nicht die ursprüngliche Frage war. :( Angesichts Ihrer Erklärung verstehe ich, warum Sie diese Antwort geschrieben haben, aber für die Nachwelt könnte es nützlicher sein, entweder (a) Ihre Antwort zu entfernen und sie als Kommentar zu der Frage neu zu schreiben, damit @ AraK's oben angezeigt wird, oder (b) Bearbeiten Sie Ihre Antwort so, dass sie den aktuellen Titel der Frage beantwortet.
Lynn
1
Aufgrund der unterschiedlichen Absicht (en) zwischen der ursprünglichen Frage des OP und der Interpretation durch den Herausgeber scheint es, als ob die Art der ursprünglichen Anfrage unfreiwillig verschoben wurde. Während beide Fragen (Original und bearbeitet) ihre Berechtigung haben, muss diese Diskrepanz behoben werden. Ich frage jetzt: Könnte diese Antwort einem Wiki hinzugefügt werden? Dies würde möglicherweise Personen helfen, die nach dieser Art von Informationen suchen, obwohl dies nicht die ursprüngliche Frage betrifft. Danach könnte die Frage erneut bearbeitet werden, um der ursprünglichen Anfrage von dato datuashvili zu entsprechen. Nur ein besorgter Leser ...
2
Ich habe mir nur die Geschichte dieser Frage angesehen und die ursprüngliche Frage fragt eigentlich nirgendwo, wie der Code funktioniert. Die Frage, die der Herausgeber zum Titel befördert hat, ist die einzige tatsächliche Frage dort.
Plugwash
224

CHAR_BIT ist die Anzahl der Bits in char . Heutzutage verwenden fast alle Architekturen 8 Bit pro Byte, dies ist jedoch nicht immer der Fall. Einige ältere Maschinen hatten früher 7-Bit-Byte.

Es kann in gefunden werden <limits.h>.

AraK
quelle
3
Einige DSPs haben 10 oder mehr Bitbytes.
Juri Robl
63
C erfordert CHAR_BIT>=8und erlaubt viel größere Werte für DSPs, die nur eine einzige Typgröße haben, häufig 32 Bit. POSIX erfordert CHAR_BIT==8. Im Allgemeinen können Sie von jeder server- oder interaktionsorientierten Architektur für mehrere Benutzer / Multitasking ausgehen, bei der die Möglichkeit besteht, mit dem Internet verbunden zu werden oder Textdaten mit der Außenwelt auszutauschen CHAR_BIT==8.
R .. GitHub STOP HELPING ICE
6
@caf: Nein, C99 benötigt die Typen int8_tund muss uint8_texistieren. Es gibt also einen Typ von Breite 8. Da sizeofjeder Typ mit sizeof chartatsächlich kompatibel sein sizeof int8_tmuss, muss er 1 sein CHAR_BIT == 8. Ich habe hier etwas über diese Beobachtung
Jens Gustedt
22
@Jens Gustedt: Bitte zitieren Sie einen Abschnitt in der C99-Spezifikation. Von den Integer-Typen mit exakter Breite heißt es in der C99-Spezifikation "Diese Typen sind optional." (7.18.1.1/3) Die Typen mit der Mindestbreite und der schnellsten Breite sind jedoch erforderlich.
Jamesdlin
3
@ Jamesdlin & Café: Entschuldigung, ich habe die Dinge durcheinander gebracht. Ja, die Anforderung, auf die ich mich bezog, stammt tatsächlich von POSIX für stdint.h. Dort ist es also erforderlich, und es wird auch als Erweiterung des ISO C-Standards gekennzeichnet , ohne auf eine bestimmte Version dieses Standards Bezug zu nehmen. Mein Fehler.
Jens Gustedt
2

Der Versuch, sowohl die explizite Frage (was ist CHAR_BIT) als auch die implizite Frage (wie funktioniert das) in der ursprünglichen Frage zu beantworten.


Ein Zeichen in C und C ++ stellt die kleinste Speichereinheit dar, die das C-Programm adressieren kann *

CHAR_BIT in C und C ++ repräsentiert die Anzahl der Bits in einem Zeichen. Aufgrund anderer Anforderungen an den Char-Typ muss er immer mindestens 8 betragen. In der Praxis sind es auf allen modernen Allzweckcomputern genau 8, aber einige historische oder spezialisierte Systeme können höhere Werte haben.

Java hat keine Entsprechung zu CHAR_BIT oder sizeof, es ist nicht erforderlich, da alle primitiven Typen in Java eine feste Größe haben und die interne Struktur von Objekten für den Programmierer undurchsichtig ist. Wenn Sie diesen Code nach Java übersetzen, können Sie einfach "sizeof (int) * CHAR_BIT - 1" durch den festen Wert 31 ersetzen.

In diesem speziellen Code wird es verwendet, um die Anzahl der Bits in einem int zu berechnen. Beachten Sie, dass bei dieser Berechnung davon ausgegangen wird, dass der Typ int keine Füllbits enthält.

Angenommen, Ihr Compiler wählt die Vorzeichenverlängerung bei Bitverschiebungen vorzeichenbehafteter Zahlen und nimmt an, dass Ihr System die 2s-Komplementdarstellung für negative Zahlen verwendet, bedeutet dies, dass "MASK" für einen positiven oder Nullwert 0 und für einen negativen Wert -1 ist.

Um eine Zweierkomplementzahl zu negieren, müssen wir eine bitweise nicht ausführen und dann eine hinzufügen. Ebenso können wir einen subtrahieren und ihn dann bitweise negieren.

Wiederum unter der Annahme, dass die Zweierkomplementdarstellung -1 durch alle Einsen dargestellt wird, ist exklusiv oder mit -1 gleichbedeutend mit einer bitweisen Negation.

Wenn also v Null ist, bleibt die Zahl allein, wenn v eins ist, wird sie negiert.

Beachten Sie, dass der signierte Überlauf in C und C ++ ein undefiniertes Verhalten ist. Die Verwendung dieser ABS-Implementierung für den negativsten Wert führt also zu undefiniertem Verhalten. Dies kann durch Hinzufügen von Casts behoben werden, sodass die letzte Zeile des Programms in int ohne Vorzeichen ausgewertet wird.

* Dies entspricht normalerweise, aber nicht unbedingt der kleinsten Speichereinheit, die die Hardware adressieren kann. Eine Implementierung kann möglicherweise mehrere Einheiten des hardwareadressierbaren Speichers zu einer Einheit des programmadressierbaren Speichers kombinieren oder eine Einheit des hardwareadressierbaren Speichers in mehrere Einheiten des programmadressierbaren Speichers aufteilen.

Plugwash
quelle