Битовые поля в C

Опубликовано: 21 Января, 2022

In C, we can specify size (in bits) of structure and union members. The idea is to use memory efficiently when we know that the value of a field or group of fields will never exceed a limit or is withing a small range. 
For example, consider the following declaration of date without the use of bit fields.
 

C

#include <stdio.h>
 
// A simple representation of the date
struct date {
    unsigned int d;
    unsigned int m;
    unsigned int y;
};
 
int main()
{
    printf("Size of date is %lu bytes ",
           sizeof(struct date));
    struct date dt = { 31, 12, 2014 };
    printf("Date is %d/%d/%d", dt.d, dt.m, dt.y);
}
Output: 
Size of date is 12 bytes
Date is 31/12/2014

 

Вышеупомянутое представление даты занимает 12 байтов в компиляторе, а целое число без знака занимает 4 байта. Поскольку мы знаем, что значение d всегда от 1 до 31, значение m от 1 до 12, мы можем оптимизировать пространство, используя битовые поля.

Выход:
 Размер даты 8 байт
Дата 31.12.2014

Однако, если тот же код написан с использованием подписанного int, а значение полей выходит за рамки битов, выделенных для переменной, может произойти что-то интересное. Например, рассмотрим тот же код, но с целыми числами со знаком:

The output comes out to be negative. What happened behind is that the value 31 was stored in 5 bit signed integer which is equal to 11111. The MSB is a 1, so it’s a negative number and you need to calculate the 2’s complement of the binary number to get its actual value which is what is done internally. By calculating 2’s complement you will arrive at the value 00001 which is equivalent to decimal number 1 and since it was a negative number you get a -1. A similar thing happens to 12 in which case you get 4-bit representation as 1100 which on calculating 2’s complement you get the value of -4.
Following are some interesting facts about bit fields in C.
1) A special unnamed bit field of size 0 is used to force alignment on next boundary. For example consider the following program. 
 

C

#include <stdio.h>
 
// A structure without forced alignment
struct test1 {
    unsigned int x : 5;
    unsigned int y : 8;
};
 
// A structure with forced alignment
struct test2 {
    unsigned int x : 5;
    unsigned int : 0;
    unsigned int y : 8;
};
 
int main()
{
    printf("Size of test1 is %lu bytes ",
           sizeof(struct test1));
    printf("Size of test2 is %lu bytes ",
           sizeof(struct test2));
    return 0;
}
Output: 
Size of test1 is 4 bytes
Size of test2 is 8 bytes

 

 
2) We cannot have pointers to bit field members as they may not start at a byte boundary. 
 

C

#include <stdio.h>
struct test {
    unsigned int x : 5;
    unsigned int y : 5;
    unsigned int z;
};
int main()
{
    struct test t;
 
    // Uncommenting the following line will make
    // the program compile and run
    printf("Address of t.x is %p", &t.x);
 
    // The below line works fine as z is not a
    // bit field member
    printf("Address of t.z is %p", &t.z);
    return 0;
}

Выход:

 prog.c: В функции main:
prog.c: 14: 1: ошибка: невозможно принять адрес битового поля 'x'
 printf ("Адрес tx -% p", & t.x); 
 ^

 
3) It is implementation defined to assign an out-of-range value to a bit field member. 
 

C



#include <stdio.h>
struct test {
    unsigned int x : 2;
    unsigned int y : 2;
    unsigned int z : 2;
};
int main()
{
    struct test t;
    t.x = 5;
    printf("%d", t.x);
    return 0;
}

Выход:

 Зависит от реализации

 
4) In C++, we can have static members in a structure/class, but bit fields cannot be static. 
 

CPP

// The below C++ program compiles and runs fine
struct test1 {
    static unsigned int x;
};
int main() {}
Output: 
 

 

CPP

// But below C++ program fails in the compilation
// as bit fields cannot be static
struct test1 {
    static unsigned int x : 5;
};
int main() {}

Выход:

 prog.cpp: 5: 29: ошибка: статический член 'x' не может быть битовым полем
     статический беззнаковый int x: 5;
                             ^

 
5) Array of bit fields is not allowed. For example, the below program fails in the compilation. 
 

C

struct test {
    unsigned int x[10] : 5;
};
 
int main()
{
}

Выход:

 prog.c: 3: 1: ошибка: битовое поле 'x' имеет недопустимый тип
 беззнаковый int x [10]: 5; 
 ^

  
 
Exercise: 
Predict the output of following programs. Assume that unsigned int takes 4 bytes and long int takes 8 bytes. 
1) 
 

CPP

#include <stdio.h>
struct test {
    unsigned int x;
    unsigned int y : 33;
    unsigned int z;
};
int main()
{
    printf("%lu", sizeof(struct test));
    return 0;
}

 
2) 
 

CPP

#include <stdio.h>
struct test {
    unsigned int x;
    long int y : 33;
    unsigned int z;
};
int main()
{
    struct test t;
    unsigned int* ptr1 = &t.x;
    unsigned int* ptr2 = &t.z;
    printf("%d", ptr2 - ptr1);
    return 0;
}

 
3) 
 

CPP

union test {
    unsigned int x : 3;
    unsigned int y : 3;
    int z;
};
 
int main()
{
    union test t;
    t.x = 5;
    t.y = 4;
    t.z = 1;
    printf("t.x = %d, t.y = %d, t.z = %d",
           t.x, t.y, t.z);
    return 0;
}


4) Используйте битовые поля в C, чтобы выяснить, является ли машина прямым или прямым порядком байтов.
Приложения -

  • Если объем памяти ограничен, мы можем использовать битовое поле.
  • Когда устройства передают состояние или информацию, закодированную в несколько битов, для этого типа ситуаций наиболее эффективны битовые поля.
  • Процедуры шифрования нуждаются в доступе к битам в байте, в этой ситуации битовое поле весьма полезно.

Пожалуйста, напишите комментарии, если вы обнаружите что-то неправильное, или вы хотите поделиться дополнительной информацией по теме, обсужденной выше.

Вниманию читателя! Не прекращайте учиться сейчас. Освойте все важные концепции DSA с помощью самостоятельного курса DSA по приемлемой для студентов цене и будьте готовы к работе в отрасли. Чтобы завершить подготовку от изучения языка к DS Algo и многому другому, см. Полный курс подготовки к собеседованию .

Если вы хотите посещать живые занятия с отраслевыми экспертами, пожалуйста, обращайтесь к Geeks Classes Live и Geeks Classes Live USA.

C