2015-10-01 15 views
6

In ctype.h, line 20, __ismask è definito come:Cosa fa (int) (unsigned char) (x) do in C?

#define __ismask(x) (_ctype[(int)(unsigned char)(x)]) 

Cosa (int)(unsigned char)(x) fare? Immagino che lanci x in unsigned char (per recuperare solo il primo byte indipendentemente da x), ma allora perché viene lanciato su uno int alla fine?

+0

il cast to int è ridondante – sp2danny

risposta

11

(unsigned char)(x) calcola in modo efficace uno unsigned char con il valore di x % (UCHAR_MAX + 1). Questo ha l'effetto di dare un valore positivo (tra 0 e UCHAR_MAX). Con la maggior parte delle implementazioni UCHAR_MAX ha un valore di 255 (sebbene lo standard permetta a un unsigned char di supportare un intervallo più ampio, tali implementazioni sono insolite).

Poiché il risultato di (unsigned char)(x) è garantito nell'intervallo supportato da un int, la conversione in int non cambierà valore.

L'effetto netto è il byte meno significativo, con un valore positivo.

Alcuni compilatori forniscono un avviso quando si utilizza un tipo char (firmato o meno) come indice di matrice. La conversione in int chiude il compilatore.

+1

Questa è la risposta: le guide di stile rigorose possono proibire alcune conversioni implicite (o anche tutte). Il cast esiste semplicemente per mostrare cosa avrebbe fatto la promozione intera. – Potatoswatter

+0

Vedo, grazie. Quindi questa è la ragione per lanciare in 'int'. –

0

Penso che char dipenda dall'implementazione, sia signed o unsigned. Quindi devi essere esplicito scrivendo unsigned char, per non trasmettere un numero negativo. Quindi trasmettere a int.

2

Un cast unsigned char estrae sicuro meno significativi CHAR_BIT s di x, a causa delle proprietà avvolgenti di tipo unsigned. (Un cast a char potrebbe essere indefinito se un char è un tipo signed su una piattaforma: il superamento di un tipo firmato è un comportamento non definito in c). CHAR_BIT è in genere 8.

Il cast a int quindi converte lo unsigned char. Lo standard garantisce che un int possa sempre contenere qualsiasi valore che può assumere unsigned char.

Un'alternativa migliore, se si desidera estrarre gli 8 bit meno significativi sarebbe applicare & 0xFF e trasmettere tale risultato a un tipo unsigned.

+2

Lo standard richiede un 'char unsigned 'per supportare un intervallo di almeno' [0,255] '. Non c'è nulla che impedisca un'implementazione che fornisce un 'char unsigned 'con un massimo maggiore. – Peter

2

Il unsigned char -cast è per assicurarsi che il valore è compreso nell'intervallo 0..255, il valore risultante viene quindi utilizzato come indice nell'array _ctype che è di 255 byte grande, vedi ctype.h in Linux.

+0

Grazie per tutte le risposte. Ma mi chiedo, perché dovremmo trasmettere a 'int', quando' unsigned char' è abbastanza grande da coprire l'array '_ctype'? –