Molto buona domanda, che espone le differenze tra C89, C99 e C++. Quindi questo è un commento su questi standard.
In C89, dove n è un int:
(unsigned)n
non è ben definito per ogni n: non c'è alcuna limitazione sulla conversione di int o senza segno eccetto che la rappresentazione di un int non negativo firmata è identico a quello di un int unsigned dello stesso valore, a condizione che il valore sia rappresentabile.
Questo è stato considerato un difetto, e in C99, purtroppo c'è un tentativo errato di limitare la codifica nel complemento a due, un complemento, o la grandezza firmato con lo stesso numero di bit. Sfortunatamente il comitato C non ha avuto molte conoscenze matematiche e ha completamente confuso le specifiche: da un lato è mal formato a causa di una definizione circolare e quindi non normativa, e d'altra parte, se si scusa questo errore, è una sovrascrittura lorda, che, ad esempio, esclude una rappresentazione BCD (utilizzata in C su mainframe IBM precedenti) e consente al programmatore di modificare il valore di un intero mediante bit di manipolazione della rappresentazione (che è molto cattivo).
C++ è andato a qualche problema per fornire una specifica migliore, tuttavia soffre dello stesso errore di definizione circolare.
In parole povere, la rappresentazione di un valore v è una matrice di caratteri senza segno con elementi sizeof (v). Un char senza segno ha una potenza di due numeri di elementi, ed è necessario che sia sufficientemente grande da garantire che codifichi fedelmente qualsiasi struttura di dati con alias. Il numero di bit in un char senza segno è ben definito come il registro binario del numero di valori rappresentabili.
Il numero di bit di qualsiasi valore senza segno è ugualmente ben definito se ha una potenza di due numeri di valori da 0 a 2^n-1, tramite lo schema di codifica di posizione canonica.
Purtroppo, il comitato ha voluto chiedere se ci fossero "buchi" nella rappresentazione. Ad esempio, potresti avere un intero 31 bit su una macchina x86? Dico sfortunatamente, perché questa è una domanda mal formata, e la risposta è ugualmente impropria.
Il modo corretto per fare questa domanda è chiedere se la rappresentazione è piena. Non è possibile parlare di "i bit di una rappresentazione" per interi con segno perché la specifica non passa dalla rappresentazione ai valori, ma va dall'altra parte. Ciò potrebbe confondere un sacco di programmatori che pensano erroneamente che una rappresentazione sia una mappatura da bit sottostanti ad un certo valore: una rappresentazione è una mappatura dai valori ai bit.
Una rappresentazione è piena se è una sorpresa, cioè è nell'intero intervallo dello spazio di rappresentazione. Se la rappresentazione è piena, non ci sono "buchi", cioè bit inutilizzati. Comunque non è tutto. Una rappresentazione di 255 valori su un array di 8 bit non può essere piena, ma non ci sono bit che non sono utilizzati. Non ci sono buchi
Il problema è questo: si consideri un int unsigned, quindi ci sono DUE rappresentazioni bitwise distinte. Esiste la matrice ben definita di log base 2 bit determinata dalla codifica canonica, e quindi c'è l'array di bit della rappresentazione fisica data dall'aliasing di una matrice di char senza segno. Anche se questa rappresentazione è piena, c'è nessuna corrispondenza tra i due tipi di bit.
Sappiamo tutti che i "bit di ordine elevato" della rappresentazione logica possono trovarsi a un'estremità della rappresentazione fisica su alcune macchine e l'altra su altre macchine: si chiama endianità.Ma in realtà non c'è ragione per cui i bit non possano essere permutati in nessun ordine, infatti non c'è motivo per cui i bit debbano essere allineati! Basti pensare di aggiungere 1 modulo al valore massimo più 1 come rappresentazione per vederlo.
Quindi ora il problema è che per gli interi con segno c'è no rappresentazione logica canonica, piuttosto ce ne sono molti comuni: il complemento a due, per esempio. Tuttavia come sopra questo è non correlato alla rappresentazione fisica. Il comitato C non ha potuto capire che la corrispondenza tra i valori e la rappresentazione fisica non può essere specificata parlando dei bit. È necessario specificare interamente parlando delle proprietà delle funzioni.
Poiché ciò non è stato fatto, lo standard C99 contiene termini non normativi e di conseguenza tutte le regole per il comportamento delle conversioni di interi con segno e senza segno sono anch'esse non-normative.
Pertanto non è chiaro che
(unsigned)n
sarà effettivamente produrre il risultato desiderato per i valori negativi.
C'è uno più negativo complemento a due interi che positivo, quindi sì, si può traboccare. –