co robi i 0xFF?

i dodanie liczby całkowitej z 0xFF pozostawia tylko najmniej znaczący bajt. Na przykład, aby uzyskać pierwszy bajt w short s, możesz napisać s & 0xFF. Jest to zwykle określane jako „maskowanie”. Jeśli byte1 jest typem pojedynczego bajtu (jak uint8_t) lub jest już mniejszy niż 256 (i w rezultacie wszystkie zera z wyjątkiem najmniej znaczącego bajtu), nie ma potrzeby maskowania wyższych bitów, ponieważ są one już zerowe.

Zobacz odpowiedź tristopiapatricka Schlütera poniżej, kiedy możesz pracować z podpisanymi typami. Podczas wykonywania operacji bitowych zalecam pracę tylko z niepodpisanymi typami.

jeśli byte1 jest 8-bitowym typem liczby całkowitej, to nie ma sensu – jeśli jest więcej niż 8 bitów, zasadniczo da ci ostatnie 8 bitów wartości:

 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 & 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 ------------------------------- 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1

niebezpieczeństwo drugiego wyrażenia pojawia się, gdy typ byte1 jest char. W takim przypadku niektóre implementacje mogą mieć wartość signed char, co spowoduje rozszerzenie znaku podczas ewaluacji.

signed char byte1 = 0x80;signed char byte2 = 0x10;unsigned short value1 = ((byte2 << 8) | (byte1 & 0xFF));unsigned short value2 = ((byte2 << 8) | byte1);printf("value1=%hu %hx\n", value1, value1);printf("value2=%hu %hx\n", value2, value2);

wydrukuje

value1=4224 1080 rightvalue2=65408 ff80 wrong!!

próbowałem go na GCC v3.4.6 na Solarisie SPARC 64 bit i wynik jest taki sam z byte1 i byte2 zadeklarowanych jako char.

TL;DR

maskowanie ma na celu uniknięcie domyślnego rozszerzenia znaku.

EDIT: sprawdziłem, to samo zachowanie w C++.

EDIT2: zgodnie z żądaniem wyjaśnienia rozszerzenia znaku.Rozszerzenie znaku jest konsekwencją sposobu, w jaki C ocenia wyrażenia. W C istnieje reguła zwana regułą awansu. C domyślnie rzuci wszystkie małe typy na int przed wykonaniem oceny. Zobaczmy, co stanie się z naszą ekspresją:

unsigned short value2 = ((byte2 << 8) | byte1);

byte1 jest zmienną zawierającą wzór bitowy 0xFF. Jeśli char jest unsigned to wartość jest interpretowana jako 255, jeśli signed to -128. Podczas wykonywania obliczeń, C rozszerzy wartość do rozmiaru int (ogólnie 16 lub 32 bitów). Oznacza to, że jeśli zmienna jest unsigned i zachowamy wartość 255, to wzór bitowy tej wartości jako int będzie równy 0x000000FF. Jeśli jest to signed chcemy mieć wartość -128, której bitowy wzorzec to 0xFFFFFFFF. Znak został rozszerzony do rozmiarów tempory używanej do obliczeń.I w ten sposób Oring tymczasowy przyniesie zły wynik.

przy montażu x86 robi się to za pomocą instrukcji movsx (movzx dla rozszerzenia zerowego). Inne procesory miały inne instrukcje (6809 miał SEX).

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.