2009-02-23 2 views
0

Я видел следующее, отправленное одним из участников stackoverflower, и это вроде меня ошеломило.Операции смены

ли кто-нибудь объяснить движущиеся операции в следующем фрагменте кода:

std::vector<bool> a; 
a.push_back(true); 
a.push_back(false); 
//... 
for (auto it = a.begin(); it != a.end();) // see 0x for meaning of auto 
{ 
    unsigned b = 0; 
    for (int i = 0; i < 8*sizeof(b); ++i) 
    { 
     b |= (*it & 1) << (8*sizeof(b) - 1 - i); 
     ++it; 
    } 
    // flush 'b' 
} 
+0

В основном дубликат куча вопросов. Один пример: http: // stackoverflow.com/questions/141525/absolute-beginners-guide-to-bit-shifting – Dana

+0

Спасибо, я посмотрю на них ... – 2009-02-23 19:37:49

+0

Ха-ха, Эй, я написал это ...: P –

ответ

3

8 * SizeOf (б) количество битов, которые могут быть сохранены в «B» (который представляет собой беззнаковое целочисленное значение, т.е. обычно 32 или 64 бита).

Что делает код, так это то, что он упаковывает логические значения в вектор 'a', чтобы стать битами в 'b'.

«* it & 1« evalutes to 1, если логическое значение в * имеет значение TRUE, иначе 0. Затем бит сдвинут влево на 32 бит минус 1 минус индекс «i», т.е. сдвинут влево от нуля до 31 биты. Это означает, что первый элемент «a» будет контролировать самый старший бит на «b» (левый сдвиг 31), второй элемент - второй самый старший бит на «b» (левый сдвиг 30) и т. Д. Обратите внимание, что в C сдвиги являются арифметическими, то есть независимо от байта или порядка бит, x < < 1 всегда x * 2.

Так, например, если ваш вектор имеет первый и 30-й набор элементов, 'b' должен содержать в конце дня двоичный номер 10000000 00000000 00000000 00000100.

0

Ответ antti.huima выглядит прямо на меня.

Однако может возникнуть ошибка в процедуре. Внешний цикл идет от a.begin до a.end, однако внутренний цикл увеличивает его, независимо от того, заставляет ли он «пройти» мимо a.end.

Если вы передадите вектор с «нечетным» размером, скажем 33 записи, результат может быть неправильным.

Это может быть не ошибка, если размер вектора гарантирован (но, возможно, должен быть тест, что длина действительна).

0

Что там происходит:

(*it & 1) 

это должно быть 0 или 1 в зависимости от BOOL быть истинным или ложным; Отметим, однако, что Bools всегда 0 или 1 так что это может быть просто (без знака) * это

<< (8*sizeof(b) - 1 - i) 

Это сдвиг, который перемещает бит от Тхи крайнего правого положения в я -го от оставил. Мы смещаем число, которое имеет не более одного бита, поэтому у него будет i -й самый левый бит, установленный или нет. Остальные биты равны нулю.

b |= ... 

это устанавливает эти биты в b, которые находятся на в РИТ.

i++; 

Перейти к следующему номеру ввода. Будьте осторожны, чтобы оставаться во входном диапазоне.

Это означает, что все это установит биты в b, соответствующие векторным элементам, которые являются истинными.