In primo luogo, non è necessario il cast: il valore di a
viene convertito in modo implicito unsigned int
con il compito di b
. Quindi, la sua dichiarazione è equivalente a:
unsigned int b = a;
Ora, una proprietà importante di unsigned
tipi interi in C e C++ è che i loro valori sono sempre nel range [0, max], dove max per unsigned int
è UINT_MAX
(è definito in limits.h
). Se assegni un valore che non è compreso nell'intervallo, viene convertito in tale intervallo. Pertanto, se il valore è negativo, aggiungere ripetutamente UINT_MAX+1
per inserirlo nell'intervallo [0, UINT_MAX
]. Per il tuo codice sopra, è come se scrivessimo: unsigned int b = (UINT_MAX + a) + 1
. Questo non è uguale a -a
(534).
Si noti che quanto sopra è vero se la rappresentazione sottostante è in complemento a due, complemento di uno, o grandezza del segno (o qualsiasi altra codifica esotica). Si vede che con qualcosa di simile:
signed char c = -1;
unsigned int u = c;
printf("%u\n", u);
assert(u == UINT_MAX);
Su macchina complemento di una tipica due con un 4 byte int
, c
è 0xff
, e u
è 0xffffffff
. Il compilatore deve assicurarsi che quando il valore -1
viene assegnato a u
, viene convertito in un valore uguale a UINT_MAX
.
Ora tornando al codice, la stringa di formato printf
è errata per b
. Dovresti usare %u
. Quando lo fai, troverai che stampa il valore di UINT_MAX - 534 + 1
invece di 534
.
Quando utilizzato l'operatore di confronto <
, poiché b
è unsigned int
, a
è anche convertito unsigned int
. Questo, dato con b = a
; in precedenza, significa che a < b
è false: a
come unsigned int
equivale a b
.
Diciamo che avete macchina complemento a quelli, e lo fai:
signed char c = -1;
unsigned char uc = c;
Diciamo un char
(con o senza segno) è di 8-bit su quella macchina. Poi c
e uc
memorizzerà i seguenti valori e bit-pattern:
+----+------+-----------+
| c | -1 | 11111110 |
+----+------+-----------+
| uc | 255 | 11111111 |
+----+------+-----------+
Nota che le sequenze di bit di c
e uc
non sono gli stessi. Il compilatore deve assicurarsi che c
abbia il valore -1
e che uc
abbia il valore UCHAR_MAX
, che è 255 su questa macchina.
Ci sono ulteriori dettagli su my answer to a question here on SO.
Probabilmente vorrete controllare i vostri documenti del compilatore e vedere se c'è un'opzione per controllare gli specificatori del formato printf. gcc ha -Wformat, che ti avrebbe avvisato della% d rispetto a% u al momento della compilazione. –
http://stackoverflow.com/questions/50605/signed-to-unsigned-conversion-in-c-is-it-always-safe –
Questo non dovrebbe avere un tag C++. – Friedrich