2012-05-25 8 views
13

Czytam plik .cpp zawierający zmienną unsigned char, próbuję przesunąć bitową lewą zmianę 16 bitów, ponieważ unsigned char składa się z 8 bitów, lewostronne 16 bitów usunie wszystkie bity i wypełni je ośmioma 0.co to oznacza bitowe przesunięcie w lewo niepodpisanego znaku z 16

unsigned char byte=0xff; byte << 16;

+4

Wartość wyrażenia nie jest przypisana. –

+2

Tak jak napisano, kompilator zoptymalizuje operację zmiany, ponieważ nie robi nic. Jaki był prawdziwy kod? –

+1

możesz na to spojrzeć: http://stackoverflow.com/questions/437470/type-to-use-to-represent-a-byte-in-ansi-c89-90-c –

Odpowiedz

16

Podczas zmiany wartości,

unsigned char x = ...; 
int y = x << 16; 

Rodzaj x jest promowany do int jeśli unsigned char pasuje W int (w większości systemów) lub unsigned jeśli unsigned char nie pasuje do int (rzadko). Tak długo jak twój int ma szerokość 25 bitów lub więcej, żadne dane nie zostaną odrzucone. .

Należy pamiętać, że jest to całkowicie niezwiązane z tym, że 16 ma typ int.

/* All three are exactly equivalent */ 
x << 16; 
x << 16u; 
x << (unsigned char) 16; 

Źródło: z n1516 (projekt C99):

§6.5.7 ustęp 3: Operatorzy przesunięcia bitowego

W promocjach całkowitymi są wykonywane na każdym z argumentów. Typ wyniku to tego z promowanego lewego operandu.

§6.3.1.1 ustęp 2: Boolean, znaków i liczb całkowitych

Jeśli int może reprezentować wszystkie wartości tego samego typu (jak ograniczona przez szerokość, do bitów pola ) , wartość jest konwertowana na int; w przeciwnym razie zostanie przekonwertowany na unsigned int. Są to tak zwane promocje bezpośrednie.

Przypisy:

: Niektóre układy DSP, jak również pewne superkomputery Cray znane są sizeof(char) == sizeof(int). Upraszcza to projektowanie jednostki magazynu ładunków procesora kosztem dodatkowego zużycia pamięci.

: Jeśli lewy shift jest promowany do int a następnie przelewa int, jest niezdefiniowane zachowanie (demony mogą wylecieć nos).Dla porównania, przepełnienie unsigned jest zawsze dobrze zdefiniowane, więc przesunięcia bitowe powinny być zwykle wykonywane na typach unsigned.

+0

Wielkie dzięki za szczegółowe wyjaśnienie. Chociaż nadal jestem zakłopotany pamięcią, może przypadkowo nadpisać po promowaniu 'unsigned char' na' int' – leomayleomay

+1

@leomayleomay: To nie tak działa. Jeśli przypiszesz 'int' do zmiennej' unsigned char', to 'int' zostanie przekonwertowane. (W końcu to nie jest asembler). –

+0

, więc lewe przesunięcie w lewo tutaj (16 w lewo) sprawi, że zmienna będzie miała 0, prawda? – leomayleomay

1

Jeśli char pasuje wewnątrz int, będzie promowany do int i wynik będzie jak można się spodziewać. Jeśli tak nie jest, jest to niezdefiniowane zachowanie zgodne ze standardem i prawdopodobnie wyemituje ostrzeżenie kompilacji. Od normy:

The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.

+1

To nigdy nie spowoduje niezdefiniowanego zachowania, jeśli 'char' nie zmieści się w' int', ponieważ musi on zatem zmieścić się wewnątrz 'unsigned int', i przesuwa się na'. unsigned int "nigdy nie są niezdefiniowane. Tylko przesunięcia na liczbach całkowitych ze znakiem są niezdefiniowane i tylko wtedy, gdy wynik matematyczny nie może być reprezentowany przez typ. Na przykład '1 << 16' jest niezdefiniowane, jeśli' int' ma 16 bitów. –

+1

Rzeczywiście, liczby całkowite są wykonywane, co oznacza, że ​​zachowanie jest nieokreślone tylko wtedy, gdy 'unsigned char' jest promowane do' int', a nie 'unsigned int', a przesunięcie wytworzyłoby wartość, która nie może być reprezentowana w' int'. – caf

+0

@DietrichEpp: Nawet '0 << 16' jest niezdefiniowanym zachowaniem, jeśli' int' ma 16 bitów, ze względu na ograniczenia zaznaczone w tej odpowiedzi. – caf