2010-08-07 2 views
4

У меня есть следующий код для самостоятельного обучения:Битовые поля в C++

#include <iostream> 
using namespace std; 
struct bitfields{ 
    unsigned field1: 3; 
    unsigned field2: 4; 
    unsigned int k: 4; 
}; 

int main(){ 
    bitfields field; 
    field.field1=8; 
    field.field2=1e7; 
    field.k=18; 
    cout<<field.k<<endl; 
    cout<<field.field1<<endl; 
    cout<<field.field2<<endl; 
    return 0; 
} 

Я знаю, что unsigned int k:4 означает, что к 4 бита, или максимальное значение 15, и результат состоит в следующем.

2 
0 
1 

Например, filed1 может быть от 0 до 7 (включительно), field2 и k от 0 до 15. Почему такой результат? Может быть, все должно быть равным нулю?

+1

bitfield, not bitfiled. – kennytm

ответ

8

Вы переполняете свои поля. В качестве примера возьмем k, это 4 бита в ширину. Он может содержать значения, как вы говорите, от 0 до 15, в двоичном представлении это

0 -> 0000 
1 -> 0001 
2 -> 0010 
3 -> 0011 
... 
14 -> 1110 
15 -> 1111 

Итак, когда вы назначаете 18, имеющий двоичную

18 -> 1 0010 (space added between 4th and 5th bit for clarity) 

k может содержать только нижние четыре бита , поэтому

k = 0010 = 2. 

Эквивалент сохраняется и для остальных ваших полей.

+1

+1: Для наглядности. – kbrimington

4

У вас есть эти результаты, потому что назначения переполняли каждое битовое поле.

Переменная filed1 имеет 3 бита, но 8 принимает 4 бита для представления (1000). Нижние три бита равны нулю, поэтому filed1 равен нулю.

Для filed2, 17 представлено 10001, но filed2 всего четыре бита. Нижние четыре бита представляют значение 1.

И, наконец, для k, 18 представлено 10010, но k всего четыре бита. Нижние четыре бита представляют собой значение 2.

Я надеюсь, что это поможет разобраться.

+2

hah! на той же секунде! :) – falstro

1

В C++ любой неподписанный тип обертывается, когда вы попадаете в его потолок [1]. Когда вы определяете бит-бит из 4 бит, то каждое добавленное вами значение также обернуто. Возможные значения для битового поля размером 4: 0-15. Если вы сохраняете «17», вы переносите на «1», а «18» - на «2».

Математически, завернутое значение исходного значения по модулю числа возможных значений для типа назначения:

Для битового поля размера 4 (2 ** 4 возможного значения):

18 % 16 == 2 
17 % 16 == 1 

для битового поля размера 3 (2 ** 3 возможных значения):

8 % 8 == 0. 

[1] Это не верно для подписали типы, где не определено, что происходит тогда.

+1

Почему это было бы неопределенным для подписанных типов? int k: 4 будет содержать от -8 до 7, присвоение 18 все равно даст два, тогда как присвоение 15 даст -1. Я предполагаю, что вторая арифметика дополнений, которая, в конце концов, является наиболее распространенной. Любая другая арифметика все равно будет четко определена, но не то же самое. – falstro

+1

Одна из целей в разработке C++ заключалась в том, чтобы быть максимально агностическим для характеристик лежащей в основе машины. Поэтому в стандартных документах не делается предположений о представлении целых чисел со знаком или их поведении: могут быть номера с 1 дополнением, и они могут * ловушку * при переполнении. –

+1

Это, конечно, важно знать. Например, есть люди, которые пишут проверки переполнения, такие как 'x + 1

Смежные вопросы