GNU/Linux >> Linux Esercitazione >  >> Linux

Esercitazione sulla programmazione in Linux C Parte 15 - Complemento a 2 secondi e numeri negativi

Finora, in questa serie di tutorial sulla programmazione C in corso, abbiamo discusso alcuni concetti, ma ne abbiamo perso uno di base. Si tratta di numeri negativi. Sì, sebbene in uno dei nostri tutorial iniziali abbiamo menzionato brevemente le variabili con segno e senza segno, in realtà non abbiamo discusso di come i numeri negativi vengono archiviati in memoria.

Bene, questo è esattamente ciò che verrà discusso in questo tutorial. Quindi, senza ulteriori indugi, iniziamo con la discussione.

complemento a 2

Prima di iniziare con la spiegazione sulla rappresentazione dei numeri negativi in ​​memoria, è importante conoscere il concetto di complemento a 1 e 2, entrambi operazioni a livello binario.

Facciamo un esempio molto semplice. Supponiamo di avere un numero intero di 4 byte 'a' con valore decimale 15. Quindi ecco come viene rappresentato nella memoria in forma binaria:

00000000 00000000 00000000 00001111

Ora, per calcolare il complemento a uno, basta invertire tutti i bit. Quindi la seguente è la rappresentazione in complemento a 1 di 15:

11111111 11111111 11111111 11110000

Ora, se aggiungi 1 alla rappresentazione binaria sopra, ottieni il complemento a 2.

11111111 11111111 11111111 11110001

Quindi la rappresentazione sopra è il complemento a due di 15.

Numeri negativi

Ora, alcuni di voi staranno pensando perché abbiamo discusso del complemento di 1 e 2? Ebbene, la risposta sta nel fatto che la rappresentazione binaria di un numero negativo viene calcolata tramite il complemento a 2.

Difficile da credere? Ecco la prova:

Il complemento a 2 che abbiamo calcolato nella sezione precedente può essere rappresentato in forma esadecimale come 0xFFFFFFFF1. Ora, vediamo qual è questo valore in forma decimale tramite un programma C

Ecco il codice:

#include <stdio.h>

int main()
{
int a = 0xFFFFFFF1;
printf("a = %d", a);

return 0;
}

E il seguente è l'output:

a = -15

Ci credi adesso? Abbiamo iniziato con un numero '15', calcolato il suo complemento a 2 e quando abbiamo convertito nuovamente il valore del complemento a due in decimale, abbiamo scoperto che è -15.

Andando avanti, ora modifichiamo leggermente il codice per assicurarci che la chiamata printf legga il valore della variabile 'a' come un numero intero senza segno.

#include <stdio.h>

int main()
{
int a = 0xFFFFFFF1;
printf("a = %u", a);

return 0;
}

Ecco l'output ora:

a = 4294967281

Oops, l'output è cambiato e ora è un enorme valore positivo. Ma perché è successo? 0xFFFFFFFF1 non è il complemento a 2 di 15 come abbiamo visto prima?

Sì, 0xFFFFFFFF1 è un complemento a due di 15, ma se non lo guardi da quella prospettiva, è anche un valore normale (4294967281). La differenza sta nel modo in cui viene letto. Se viene letto come intero con segno (tramite %d in printf), vedrai l'output come -15, ma se viene letto come intero senza segno (tramite %u in printf), vedrai l'output come 4294967281.

Come regola pratica con le variabili con segno (che trattano sia valori negativi che positivi), tieni presente che la rappresentazione binaria di numeri negativi ha sempre '1' come bit più a sinistra, mentre in caso di numeri positivi il bit in questione è sempre 0.  

Infine, nota che puoi anche invertire una rappresentazione in complemento a due per ottenere la sua controparte positiva. Ad esempio, prendiamo di nuovo il valore 0xFFFFFFF1, che è la rappresentazione esadecimale di -15. È rappresentato in forma binaria come:

11111111 11111111 11111111 11110001

Ora, per ottenere la sua controparte positiva, esegui di nuovo un complemento a 2. Ciò significa che prima fai un complemento a 1:

00000000 00000000 00000000 00001110

E poi aggiungi 1

00000000 00000000 00000000 00001111

Ora, se lo converti, otterrai il valore 15 in forma decimale.

Conclusione

Spero che questo tutorial ti abbia aiutato a capire il concetto di numeri negativi nel contesto di come sono rappresentati nella memoria. Ti suggerisco di provare gli esempi che abbiamo utilizzato in questo tutorial e, in caso di problemi, dubbi o domande, lasciaci un commento qui sotto.


Linux
  1. C Tutorial di programmazione Parte 5 - Variabili di carattere

  2. Esercitazione sulla programmazione C Linux Parte 10 - Ambiti variabili

  3. Esercitazione sulla programmazione C Linux Parte 9:Stringhe

  4. Esercitazione sulla programmazione C Linux Parte 8 - Chiamata per valore Vs Chiamata per puntatore/indirizzo

  5. Esercitazione sulla programmazione C Linux Parte 8 - Chiamata per valore Vs Chiamata per puntatore/indirizzo

5 interessanti suggerimenti e trucchi per la riga di comando in Linux - Parte 1

Come confrontare e unire file di testo su Linux (parte 2)

Esercitazione sulla programmazione C Linux Parte 18:Funzioni ricorsive

Come installare e utilizzare KompoZer in Linux - Tutorial

Discussione su Windows, Linux e cPanel VPS – Parte II

L'ordinamento di Linux non funziona con numeri float negativi