Cos'è CHAR_BIT?


91

Citando il codice per calcolare il valore assoluto intero (abs) senza diramazioni da 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;

Variante brevettata:

r = (v ^ mask) - mask;

Cos'è CHAR_BITe come usarlo?

Risposte:


-1

È necessario essere consapevoli del fatto che questo codice dipende dal comportamento definito dall'implementazione del bitshift destro sui tipi firmati. gcc promette di dare sempre il comportamento sano (segno-bit-estensione) ma ISO C consente all'implementazione di riempire a zero i bit superiori.

Un modo per aggirare questo problema:

#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

Il tuo Makefileo config.hecc. Può essere definito HAVE_SIGN_EXTENDING_BITSHIFTal momento della creazione a seconda della piattaforma.


120
Non capisco come questa possa essere una risposta accettata in quanto non risponde alla domanda, anche se è un commento molto interessante.
qdii

15
@Mauris: Qualcuno ha modificato la domanda e ha promosso una sotto-domanda al titolo della domanda. Il titolo originale era certamente orribile, ma la domanda dell'OP riguardava il funzionamento del citato codice di hacking e "non funziona, almeno non portabile, ed ecco perché" è una risposta utile.
R .. GitHub SMETTA DI AIUTARE IL GHIACCIO

12
Ah capisco. Purtroppo, questa domanda compare molto in alto nei risultati di ricerca di Google per "Che cos'è CHAR_BIT?" , anche se quella non era la domanda originale. :( Data la tua spiegazione, capisco perché hai scritto questa risposta, ma per i posteri potrebbe essere più utile (a) rimuovere la tua risposta e riscriverla come commento alla domanda, in modo che @ AraK compaia in cima, o (b) modifica la tua risposta in modo che risponda al titolo corrente della domanda.
Lynn

1
A causa della differenza di intenzioni tra la domanda originale del PO e la sua interpretazione dell'editore, sembra che la natura della richiesta originale sia stata involontariamente spostata. Sebbene entrambe le domande (originale e modificata) siano valide, questa discrepanza deve essere affrontata. Ora chiedo: questa risposta potrebbe essere aggiunta a un wiki? Questo potrebbe aiutare le persone che stanno cercando questo tipo di informazioni, anche se non riguarda la domanda originale. Dopodiché, la domanda potrebbe essere modificata di nuovo, per adattarsi alla richiesta originale di dato datuashvili. Solo un lettore preoccupato ...

2
Ho appena guardato la storia di questa domanda e la domanda originale in realtà non chiede da nessuna parte come funziona il codice. La domanda che l'editore ha promosso al titolo è l'unica vera domanda lì dentro.
plugwash

224

CHAR_BITè il numero di bit in char. Oggigiorno, quasi tutte le architetture usano 8 bit per byte, ma non è sempre così. Alcune macchine meno recenti avevano byte a 7 bit.

Può essere trovato in <limits.h>.


3
Alcuni DSP hanno 10 o più bit-byte.
Juri Robl

64
C richiede CHAR_BIT>=8e consente valori molto più grandi per i DSP che hanno una sola dimensione di tipo, spesso 32 bit. POSIX richiede CHAR_BIT==8. In generale, puoi assumere qualsiasi architettura multiutente / multitasking orientata al server o orientata all'uso interattivo con qualsiasi possibilità di essere connesso a Internet o di scambiare dati testuali con il mondo esterno CHAR_BIT==8.
R .. GitHub SMETTA DI AIUTARE IL GHIACCIO

6
@caf: No, è che C99 richiede i tipi int8_te uint8_tper esistere. Quindi esiste un tipo di larghezza 8. Poiché sizeofqualsiasi tipo deve essere compatibile con sizeof chareffettivamente sizeof int8_tdeve essere 1. Quindi CHAR_BIT == 8. Ho scritto qualcosa su quell'osservazione qui: gustedt.wordpress.com/2010/06/01/how-many-bits-has-a-byte
Jens Gustedt

22
@ Jens Gustedt: si prega di citare una sezione nelle specifiche C99. Dei tipi interi di larghezza esatta, la specifica C99 dice "Questi tipi sono opzionali". (7.18.1.1/3) Tuttavia, sono obbligatori i tipi di larghezza minima e larghezza massima.
jamesdlin

3
@jamesdlin & caf: scusa se ho confuso le cose. sì, il requisito a cui mi riferivo proviene effettivamente da POSIX per stdint.h. Quindi è necessario, ed è anche contrassegnato come Estensione allo standard ISO C , senza fare riferimento a una particolare versione di quello standard. Colpa mia.
Jens Gustedt

2

Cercando di rispondere sia alla domanda esplicita (cos'è CHAR_BIT) sia alla domanda implicita (come funziona) nella domanda originale.


Un carattere in C e C ++ rappresenta la più piccola unità di memoria che il programma C può indirizzare *

CHAR_BIT in C e C ++ rappresenta il numero di bit in un carattere. Deve sempre essere almeno 8 a causa di altri requisiti sul tipo char. In pratica su tutti i moderni computer di uso generale è esattamente 8 ma alcuni sistemi storici o specialistici possono avere valori più alti.

Java non ha equivalenti a CHAR_BIT o sizeof, non ce n'è bisogno poiché tutti i tipi primitivi in ​​Java sono di dimensioni fisse e la struttura interna degli oggetti è opaca per il programmatore. Se traduci questo codice in Java puoi semplicemente sostituire "sizeof (int) * CHAR_BIT - 1" con il valore fisso 31.

In questo particolare codice viene utilizzato per calcolare il numero di bit in un int. Tieni presente che questo calcolo presuppone che il tipo int non contenga bit di riempimento.

Supponendo che il tuo compilatore scelga di estendere il segno su spostamenti di bit di numeri con segno e supponendo che il tuo sistema usi la rappresentazione in complemento di 2 per i numeri negativi, ciò significa che "MASK" sarà 0 per un valore positivo o zero e -1 per un valore negativo.

Per negare un numero di complemento a due dobbiamo eseguire un no bit per bit e quindi aggiungerne uno. In modo equivoco possiamo sottrarne uno e poi negarlo bit per bit.

Anche in questo caso assumendo che la rappresentazione in complemento a due sia -1 è rappresentata da tutti, quindi esclusivo o con -1 è equivalente alla negazione bit per bit.

Quindi quando v è zero il numero viene lasciato solo, quando v è uno viene negato.

Bisogna tenere presente che l'overflow con segno in C e C ++ è un comportamento indefinito. Quindi l'utilizzo di questa implementazione ABS sul valore più negativo porta a un comportamento indefinito. Questo può essere risolto aggiungendo cast in modo tale che la riga finale del programma venga valutata in unsigned int.

* Che è solitamente, ma non in modo nesacerale, la stessa unità di memoria più piccola che l'hardware può indirizzare. Un'implementazione può potenzialmente combinare più unità di memoria indirizzabile tramite hardware in una unità di memoria indirizzabile tramite programma o dividere un'unità di memoria indirizzabile tramite hardware in più unità di memoria indirizzabile tramite programma.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.