Czytając odpowiedzi na to pytanie, natknąłem się na ten komentarz [zredagowany].
Uzupełnienie 2 do 0100 (4) wyniesie 1100. Teraz 1100 to 12, jeśli mówię normalnie. Tak więc, kiedy mówię normalny 1100, to jest to 12, ale kiedy mówię, że 1100 uzupełnienia 2 to wtedy -4? Także w Javie, gdy 1100 (na razie załóżmy 4 bity), to jak to ustalić, czy jest to +12 czy -4 ?? - hagrawal 2 lipca o 16:53
Moim zdaniem pytanie zadane w tym komentarzu jest dość interesujące, dlatego najpierw chciałbym je przeformułować, a następnie podać odpowiedź i przykład.
PYTANIE - Jak system może ustalić, w jaki sposób należy interpretować jeden lub więcej sąsiadujących bajtów? W szczególności, w jaki sposób system może ustalić, czy dana sekwencja bajtów jest zwykłą liczbą binarną, czy liczbą uzupełniającą 2?
ODPOWIEDŹ - System ustala sposób interpretacji sekwencji bajtów według typów. Typy definiują
- ile bajtów należy wziąć pod uwagę
- jak należy interpretować te bajty
PRZYKŁAD - poniżej zakładamy, że
char
mają 1 bajt długości
short
mają 2 bajty długości
int
i float
mają długość 4 bajtów
Należy pamiętać, że te rozmiary są specyficzne dla mojego systemu. Chociaż dość powszechne, mogą różnić się w zależności od systemu. Jeśli jesteś ciekawy, jakie są w twoim systemie, użyj operatora sizeof .
Przede wszystkim definiujemy tablicę zawierającą 4 bajty i inicjalizujemy je wszystkie na liczbę binarną 10111101
, odpowiadającą liczbie szesnastkowej BD
.
// BD(hexadecimal) = 10111101 (binary)
unsigned char l_Just4Bytes[ 4 ] = { 0xBD, 0xBD, 0xBD, 0xBD };
Następnie odczytujemy zawartość tablicy za pomocą różnych typów.
unsigned char
i signed char
// 10111101 as a PLAIN BINARY number equals 189
printf( "l_Just4Bytes as unsigned char -> %hi\n", *( ( unsigned char* )l_Just4Bytes ) );
// 10111101 as a 2'S COMPLEMENT number equals -67
printf( "l_Just4Bytes as signed char -> %i\n", *( ( signed char* )l_Just4Bytes ) );
unsigned short
i short
// 1011110110111101 as a PLAIN BINARY number equals 48573
printf( "l_Just4Bytes as unsigned short -> %hu\n", *( ( unsigned short* )l_Just4Bytes ) );
// 1011110110111101 as a 2'S COMPLEMENT number equals -16963
printf( "l_Just4Bytes as short -> %hi\n", *( ( short* )l_Just4Bytes ) );
unsigned int
, int
afloat
// 10111101101111011011110110111101 as a PLAIN BINARY number equals 3183328701
printf( "l_Just4Bytes as unsigned int -> %u\n", *( ( unsigned int* )l_Just4Bytes ) );
// 10111101101111011011110110111101 as a 2'S COMPLEMENT number equals -1111638595
printf( "l_Just4Bytes as int -> %i\n", *( ( int* )l_Just4Bytes ) );
// 10111101101111011011110110111101 as a IEEE 754 SINGLE-PRECISION number equals -0.092647
printf( "l_Just4Bytes as float -> %f\n", *( ( float* )l_Just4Bytes ) );
4 bajty w RAM ( l_Just4Bytes[ 0..3 ]
) zawsze pozostają dokładnie takie same. Jedyne, co się zmienia, to sposób ich interpretacji.
Ponownie mówimy systemowi, jak interpretować je według typów .
Na przykład powyżej użyliśmy następujących typów do interpretacji zawartości l_Just4Bytes
tablicy
unsigned char
: 1 bajt w formacie binarnym
signed char
: 1 bajt w uzupełnieniu do 2
unsigned short
: 2 bajty w zwykłym zapisie binarnym
short
: 2 bajty w uzupełnieniu do 2
unsigned int
: 4 bajty w zwykłym zapisie binarnym
int
: 4 bajty w uzupełnieniu do 2
float
: 4 bajty w notacji pojedynczej precyzji IEEE 754
[EDYCJA] Ten post został edytowany po komentarzu użytkownika4581301. Dziękujemy za poświęcenie czasu na upuszczenie tych kilku pomocnych linii!