Битовые поля — это особый вид полей структуры. Они используются для плотной упаковки данных, например, флажков типа «да/нет». Минимальная адресуемая ячейка памяти — 1 байт, а для хранения флажка достаточно одного бита. При описании битового поля после имени через двоеточие указывается длина поля в битах (целая положительная константа):
struct Options{
bool centerX:1;
bool centerY:1:
unsigned int shadow:2;
unsigned int palette:4;
}:
Битовые поля могут быть любого целого типа. Имя поля может отсутствовать, такие поля служат для выравнивания на аппаратную границу. Доступ к полю осуществляется обычным способом — по имени. Адрес поля получить нельзя, однако в остальном битовые поля можно использовать точно так же, как обычные поля структуры. Следует учитывать, что операции с отдельными битами реализуются гораздо менее эффективно, чем с байтами и словами, так как компилятор должен генерировать специальные коды, и экономия памяти под переменные оборачивается увеличением объема кода программы. Размещение битовых полей в памяти зависит от компилятора и аппаратуры.
4. Объединения
Объединение (union) представляет собой частный случай структуры, все поля которой располагаются по одному и тому же адресу. Формат описания такой же, как у структуры, только вместо ключевого слова struct используется слово union. Длина объединения равна наибольшей из длин его полей, В каждый момент времени в переменной типа объединение хранится только одно значение, и ответственность за его правильное использование лежит на программисте.
Объединения применяют для экономии памяти в тех случаях, когда известно, что больше одного поля одновременно не требуется:
#include <iostream.h>
int main(){
enum paytype {CARD, CHECK};
paytype ptype;
union payment{
char card[25];
long check;
} info;
/* присваивание значений info и ptype */
switch (ptype){
case CARD: cout « "Оплата no карте: " « info.card; break;
case CHECK: cout « "Оплата чеком: " « info.check; break;
}
return 0;
}
Объединение часто используют в качестве поля структуры, при этом в структуру удобно включить дополнительное поле, определяющее, какой именно элемент объединения используется в каждый момент. Имя объединения можно не указывать, что позволяет обращаться к его полям непосредственно:
#include <iostream.h>
int main(){
enum paytype {CARD, CHECK};
struct{
paytype ptype;
union{
char card[25];
long check;
};
} info;
... /* присваивание значения info */
switch (info.ptype){
case CARD: cout « "Оплата no карте: " « info.card; break;
case CHECK: cout « "Оплата чеком: " « info.check; break;
}
return 0;
}
Объединения применяются также для разной интерпретации одного и того же битового представления (но, как правило, в этом случае лучше использовать явные операции преобразования типов). В качестве примера рассмотрим работу со структурой, содержащей битовые поля:
struct Options{
bool centerX:1;
bool centerY:1;
unsigned int shadow:2;
unsigned int palette:4;
}:
union{
unsigned char ch;
Options bit;
}option = {0xC4};
cout « option.bit.palette;
option.ch &= 0xF0; // наложение маски
По сравнению со структурами на объединения налагаются некоторые ограничения:
• объединение может инициализироваться только значением его первого элемента;
• объединение не может содержать битовые поля;
• объединение не может содержать виртуальные методы, конструкторы, деструкторыи операцию присваивания;
• объединение не может входить в иерархию классов.