Странное поведение побитового НЕ (~) - PullRequest
11 голосов
/ 28 августа 2011

Как объяснить следующее поведение?

#include<iostream>

using namespace std;

int main(){

       unsigned char a = 8;

       cerr << "a: " << (int)a << '\n';

       unsigned char b = (~a) >> 6;

       cerr << "b: " << (int)b << '\n';

       unsigned char c = (~a);
       c = c >> 6;

       cerr << "c: " << (int)c << '\n';

       return 0;
}

Вывод:

a: 8
b: 255
c: 3

После дальнейшего тестирования кажется, что (~a) становится int, а не unsigned char,Вот почему 1 сдвинуты.

Что происходит?

РЕДАКТИРОВАТЬ: Мой компилятор просто стандартный gcc 4.1.2

Ответы [ 3 ]

22 голосов
/ 28 августа 2011

Все арифметические и побитовые операторы в C всегда расширяют свои аргументы как минимум до int, если они изначально были более короткими целочисленными типами. Вот так определяется язык. Спецификация языка называет это «интегральной рекламой».

(Основная причина этого состоит в том, чтобы упростить реализацию C на архитектурах, где аппаратное обеспечение не поддерживает эффективные операции на меньших количествах, чем полное машинное слово. Конечно, это также отчасти только потому, что так всегда работало и не может быть изменен без нарушения существующего кода, который зависит от этого поведения).

2 голосов
/ 28 августа 2011

~a = 0xFFFFFFF7, поэтому b = (~a) >> 6 приводит к b = 0xFF;В случае c у нас есть c = (~a);, что приводит к c = 0xF7, поэтому c>>6 будет 3. Хеннинг Махолм объясняет целочисленное продвижение выше.Эта статья также полезна.

0 голосов
/ 28 августа 2011
a = 8

~a = -9 (int)

~a >> 6 = -1 (int)

(unsigned char)-1 = 255
...