Как работают битовые поля

У меня есть такая задача:

Разработать битовое поле, описывающее состояния элементов прибора. Ввести с консоли число в 16-ричной системе счисления, преобразовать его в битовое поле за счёт использования объединения. Вывести на консоль состояния элементов прибора, соответствующие состоянию битов во введённом числе.

Варианты приборов и их элементов:

Клавиатура. Элементы: NumLock вкл/выкл, CapsLock вкл/выкл, ScrollLock вкл/выкл.

Вот мой код:

enum {
    NUMLOCK = 0b0001,
    CAPSLOCK = 0b0010,
    SCROLLLOCK = 0b0100
};

union {
    struct {
        unsigned char NumLock : 1;
        unsigned char CapsLock : 1;
        unsigned char ScrollLock : 1;
    };
    unsigned char flags;
} condition;
 
int main() {

    condition.flags = NUMLOCK | CAPSLOCK;
    if (condition.NumLock)
        printf("NumLock is on\n");
    else
        printf("NumLock is off\n");


    if (condition.CapsLock)
        printf("CapsLock is on\n");
    else
        printf("CapsLock is off\n");


    if (condition.ScrollLock)
        printf("ScrollLock is on\n");
    else
        printf("ScrollLock is off\n");

    return 0;
}

Однако он написан неправильно из-за того, что я не понимаю что мне нужно сделать. Как преобразовать введенное число в шестнадцатеричной системе счисления в битовое поле за счет использования объединения? Я не понимаю, что означает состояние битов во введенном числе. Кто разбирается в битовых полях объясните, пожалуйста, что здесь от меня хотят и как изменить мой код в правильную сторону. Я понимаю, что здесь скорее всего имеется ввиду то, что если бит - это единичка, то например NumLock включен, а если 0 - то выключен. Но все равно условие непонятное. Вот я попробовал ввести этот бит с консоли, но он выдает ошибку:

int bit;
enum {
    NUMLOCK = bit,
    CAPSLOCK = bit,
    SCROLLLOCK = bit
};

union {
    struct {
        unsigned char NumLock : 1;
        unsigned char CapsLock : 1;
        unsigned char ScrollLock : 1;
    };
    unsigned char flags;
} condition;
 
int main() {

    scanf_s("%x", &bit);
    condition.flags = NUMLOCK | CAPSLOCK;
    if (condition.NumLock)
        printf("NumLock is on\n");
    else
        printf("NumLock is off\n");


    if (condition.CapsLock)
        printf("CapsLock is on\n");
    else
        printf("CapsLock is off\n");


    if (condition.ScrollLock)
        printf("ScrollLock is on\n");
    else
        printf("ScrollLock is off\n");

    return 0;
}

Если точнее выражаться, то он подчеркивает красным bit в enum. Может я что-то не так понял и не туда нужно вводить бит или нужно как-то по-другому это делать?


Ответы (1 шт):

Автор решения: Max Grupper

Можно заполнить поле flags напрямую с консоли. Enum в таком варианте необходим только для понимания в каком разряде находится тот или иной флаг. Внутри объединения флаги будут уже находится на своих местах, так как NumLock, CapsLock, ScrollLock разделяют одну память с flags.

enum {
    NUMLOCK = 0b0001,
    CAPSLOCK = 0b0010,
    SCROLLLOCK = 0b0100,
};

union {
    struct {
        unsigned char NumLock : 1;
        unsigned char CapsLock : 1;
        unsigned char ScrollLock : 1;
    };
    unsigned char flags;
} condition;

int main() {
    scanf("%x", &condition.flags);
    if (condition.NumLock)
        printf("NumLock is on\n");
    else
        printf("NumLock is off\n");
    
    if (condition.CapsLock)
        printf("CapsLock is on\n");
    else
        printf("CapsLock is off\n");
    
    if (condition.ScrollLock)
        printf("ScrollLock is on\n");
    else
        printf("ScrollLock is off\n");

    return 0;
}
→ Ссылка