GNU/Linux >> Znalost Linux >  >> Linux

Linux C Programming Tutorial část 15 - 2s Doplňky a záporná čísla

Až dosud jsme v této probíhající sérii výukových programů pro programování v jazyce C diskutovali o několika konceptech, ale jeden základní jsme vynechali. Jde o záporná čísla. Ano, i když jsme se v jednom z našich úvodních tutoriálů krátce zmínili o proměnných se znaménkem a bez znaménka, ve skutečnosti jsme nediskutovali o tom, jak se záporná čísla ukládají do paměti.

No, to je přesně to, o čem bude řeč v tomto tutoriálu. Takže bez dalších řečí začněme diskuzí.

Doplněk 2

Než začneme s vysvětlením reprezentace záporných čísel v paměti, je důležité, abychom znali koncept doplňku 1 a 2, což jsou oba operace na binární úrovni.

Vezměme si velmi jednoduchý příklad. Předpokládejme, že máte 4bajtové celé číslo 'a' s desetinnou hodnotou 15. Pak je zde uvedeno, jak je reprezentováno v binární formě paměti:

00000000 00000000 00000000 00001111

Nyní, abyste vypočítali doplněk jedničky, invertujte všechny bity. Následuje tedy reprezentace doplňku 1 15:

11111111 11111111 11111111 11110000

Nyní, když přidáte 1 k výše uvedené binární reprezentaci, získáte doplněk 2.

11111111 11111111 11111111 11110001

Takže výše uvedená reprezentace je dvojkový doplněk 15.

Záporná čísla

Nyní si někteří z vás musí myslet, proč jsme diskutovali o komplementu 1 a 2? Odpověď spočívá ve skutečnosti, že binární reprezentace záporného čísla se vypočítává pomocí doplňku 2.

Těžko uvěřit? Tady je důkaz:

Doplněk 2, který jsme vypočítali v předchozí části, může být reprezentován v hexadecimálním tvaru jako 0xFFFFFFF1. Nyní se podívejme, jaká je tato hodnota v desítkovém tvaru prostřednictvím programu C

Zde je kód:

#include <stdio.h>

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

return 0;
}

A následující je výstup:

a = -15

Teď tomu věřit? Začali jsme číslem '15', vypočítali jeho dvojkový doplněk, a když jsme hodnotu dvojkového doplňku opět převedli na desítkové, zjistili jsme, že je -15.

Pokračujeme, nyní trochu vyladíme kód, abychom se ujistili, že volání printf čte hodnotu proměnné 'a' jako celé číslo bez znaménka.

#include <stdio.h>

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

return 0;
}

Tady je výstup:

a = 4294967281

Jejda, výstup se změnil a teď je to obrovská kladná hodnota. Ale proč se to stalo? Není 0xFFFFFFF1 doplňkem 2 k 15, jak jsme viděli dříve?

Ano, 0xFFFFFFF1 je dvojkový doplněk 15, ale pokud se na to nepodíváte z této perspektivy, je to také normální hodnota (4294967281). Rozdíl je v tom, jak se to čte. Pokud je čteno jako celé číslo se znaménkem (přes %d v printf), uvidíte výstup jako -15, ale pokud je čteno jako celé číslo bez znaménka (prostřednictvím %u v printf), uvidíte výstup jako 4294967281.

Jako základní pravidlo pro proměnné se znaménkem (které se zabývají zápornými i kladnými hodnotami) mějte na paměti, že binární reprezentace záporných čísel má vždy „1“ jako bit zcela vlevo, zatímco v případě kladných čísel je příslušný bit vždy 0.  

Nakonec si všimněte, že můžete také obrátit reprezentaci dvojkového doplňku, abyste získali jeho kladný protějšek. Jako příklad si opět vezměme hodnotu 0xFFFFFFF1, což je hexadecimální vyjádření -15. Je reprezentován v binární podobě jako:

11111111 11111111 11111111 11110001

Nyní, abyste získali jeho kladný protějšek, stačí znovu provést dvojkový doplněk. To znamená, že nejprve doplňte 1:

00000000 00000000 00000000 00001110

A pak přidejte 1

00000000 00000000 00000000 00001111

Nyní, pokud toto převedete, získáte hodnotu 15 v desítkovém tvaru.

Závěr

Doufám, že vám tento tutoriál pomohl pochopit koncept záporných čísel v kontextu toho, jak jsou reprezentována v paměti. Navrhuji, abyste si vyzkoušeli příklady, které jsme použili v tomto tutoriálu, a v případě, že narazíte na jakýkoli problém nebo budete mít jakékoli pochybnosti či dotaz, napište nám komentář níže.


Linux
  1. Linux nice and renice Command Tutorial (7 příkladů)

  2. C Výukový program programování 4 - Proměnné a paměť

  3. C Výukový program programování Část 3 - Základy proměnných

  1. C Výukový program programování Část 5 - Znakové proměnné

  2. Výukový program programování v Linuxu C Část 10 - Variabilní rozsahy

  3. Výukový program programování v Linuxu C Část 9:Řetězce

  1. Výukový program programování Linux C, část 8 – Volání podle hodnoty versus volání podle ukazatele/adresy

  2. Výukový program programování Linux C, část 8 – Volání podle hodnoty versus volání podle ukazatele/adresy

  3. Výukový program programování Linux C, část 8 – Volání podle hodnoty versus volání podle ukazatele/adresy