C установка IDE C структура програми C змінні C типи даних С функція printf C константи C арифметичні операції C операції порівняння і логічні операції C порозрядні операції C операції присвоювання C перетворення типів C умовні конструкції C цикли С масиви і рядки С функція scanf C препроцесор. Директива #include C #define директива C макроси C умовна компіляція C функції. Визначення та опис функцій C функції. Передача параметрів в функцію C функції. Повернення результату з функції C функції. Рекурсивні функції C область видимості змінних C зовнішні об'єкти C вказівники C вказівник. Операції з вказівниками C покажчики. Арифметика покажчиків C покажчики. Константи і покажчики C покажчики. Покажчики та масиви C покажчики. Масиви покажчиків, рядки і багаторівнева адресація C покажчики. Покажчики в параметрах функції C покажчики. Динамічна пам'ять C покажчики. Покажчик як результат функції C покажчики. Управління динамічної пам'яттю C покажчики. Покажчики на функцію C покажчики. Покажчики на функції як параметри і результати функцій C покажчики. Функції зі змінною кількістю параметрів C struct. Визначення структур C struct. Структури як елементи структур C struct. Покажчики на структури C struct. Масиви структур C struct. Структури і функції C struct. union об'єднання C struct. Бітові поля С file. Введення-виведення і робота з файлами C file. Читання і запис бінарних файлів C file. Читання і запис структур в файл C file. Читання і запис текстових файлів C file. Форматування вводу-виводу C file. Позиціонування в потоці C file. Консольне введення-виведення

C struct. Бітові поля


Бітові поля забезпечують зручний доступ до окремих біт даних. Вони дозволяють формувати об'єкти з довжиною, що не кратної байту. Що в свою чергу дозволяє економити пам'ять, більш щільно розміщуючи дані.

Бітове поле не може існувати саме по собі. Воно може бути тільки елементом структури або об'єднання. Наприклад, в рамках структури бітові поля мають наступну форму визначень:

struct імя_структури
{
    тип1 імя_поля1 : ширина_поля1;
    тип2 імя_поля2 : ширина_поля2;
    //..............
    типi імя_поляi : ширина_поляi;
}

В даному випадку тіпi представляє тип поля. В якості типу поля може використовуватися тільки int , допустимі модифікатори signed і unsigned. імя_поляi - це довільний ідентифікатор, а шіріна_поляi - позитивне ціле число, яке не повинно перевищувати довжину машинного слова для конкретної платформи (машинне слово вимірюється в бітах або байтах і одно розрядності регістрів процесора, наприклад, для архітектури 64x - довжина 64 біта).

Наприклад, визначимо структуру з бітовими полями:

struct point
{
    unsigned int x:5;   // 0-31
    unsigned int y:3;   // 0-7
};

Структура point містить два бітових поля. Перше поле x має ширину в 5 біт. Тобто воно може набувати значень від 0 до 31. Друге поле - y - має ширину в 3 біта і може приймати значення від 0 до 7.

Потім ми зможемо працювати з цією структурою і її елементами як і з будь-якою структурою:

#include <stdio.h>
 
struct point
{
    unsigned int x:5;   // 0-31
    unsigned int y:3;   // 0-7
};
 
int main(void)
{
    struct point center = {0, 5};
    center.x = 2;
    printf("x=%d    y=%d \n", center.x, center.y);  // x=2  y=5
     
    return 0;
}

Залежно від платформи розташування полів структури в пам'яті може відрізнятися. Зокрема, на Windows порядок розташування наступний: поля на початку структури мають молодші адреси, а поля в кінці структури мають старші адреси.

Так як поля x і y замість займають 8 біт, то відповідно на зображенні є 8 осередків. На трьох перших бітах розміщено поле point.y. Так як воно має значення 5, то в двійковій системі це буде 101. А на наступних 5 бітах поміщається поле point.x зі значенням 2 (тобто 10 в двійковій системі).

В принципі ми самі можемо програмним чином дізнатися розміщення полів в пам'яті. Для цього скористаємося об'єднаннями:

#include <stdio.h>
 
struct point
{
    unsigned int x:5;   // 0-31
    unsigned int y:3;   // 0-7
};
 
union code
{
    struct point p;
    struct{
        unsigned a0:1;
        unsigned a1:1;
        unsigned a2:1;
        unsigned a3:1;
        unsigned a4:1;
        unsigned a5:1;
        unsigned a6:1;
        unsigned a7:1;
    } byte;
};
 
 
int main(void)
{
    struct point center = {2, 5};
    union code c;
    c.p = center;
    printf("7 \t 6 \t 5 \t 4 \t 3 \t 2 \t 1 \t 0 \n");
    printf("%d \t %d \t %d \t %d \t %d \t %d \t %d \t %d \n", 
            c.byte.a7, c.byte.a6, c.byte.a5, c.byte.a4, 
            c.byte.a3, c.byte.a2, c.byte.a1, c.byte.a0);
    return 0;
}

Об'єднання code містить два елементи - структури point і безіменну структуру byte. Як відомо з минулого теми, елементи структури будуть займати одну і ту ж область в пам'яті, точніше будуть починатися з одного і того ж місця в пам'яті. Тому для з'ясування, які біти зайняті, безіменна структура byte має 8 полів, кожне з яких має ширину 1 біт.

І при запуску програми ми наочно зможемо побачити розміщення значень в пам'яті:

7 6 5 4 3 2 1 0
1 0 1 0 0 0 1 0

Наш партнер:
beta test mp3 playlist downloader