Fai un and sui soli bit non-di segno, quindi se il bit di segno è attivo aggiungi al risultato -2^(posizione bit segno).
Supponendo che il tuo numero "raw" stia in uno short senza segno:
Questo funziona indipendentemente da come siano rappresentati gli interi sulla tua piattaforma. Se invece assumi che sia l'input che l'output siano in complemento a due, allora si può fare:codice:short rawtoshort(unsigned short raw, unsigned int bits) { unsigned short signmask=1<<(bits-1); return ((raw&signmask)?(-(short)signmask):0) + (raw&(signmask-1)); }
in ogni caso, è più la fatica del guadagno usare questo secondo metodo in C, mentre con ogni probabilità è un pelo più efficiente/compatto rispetto all'altro se scritto direttamente in assembly.codice:short rawtoshort(unsigned short raw, unsigned int bits) { unsigned short signmask=1<<(bits-1); raw|=(raw&signmask)?(~(signmask-1)):0; short ret; // necessario dato che in C il type-punning via cast di puntatori non è standard, e così pure un buon // numero di operazioni bit-a-bit sui tipi con segno memcpy(&ret, &raw, sizeof(ret)); return ret; }

Rispondi quotando