Что означает «переменная | переменная» в C ++? - PullRequest
7 голосов
/ 23 мая 2011

Я смотрел этот демонстрационный код сторожевого таймера ITE8712, когда увидел это:

void InitWD(char cSetWatchDogUnit, char cSetTriggerSignal)
{
OpenIoConfig();     //open super IO of configuration for Super I/O

SelectIoDevice(0x07);   //select device7

//set watch dog counter of unit
WriteIoCR(0x72, cSetWatchDogUnit|cSetTriggerSignal);

//CloseIoConfig();      //close super IO of configuration for Super I/O
}

и мне интересно, что подразумевается под этой строкой:

cSetWatchDogUnit|cSetTriggerSignal

потому что функция WriteIoCR выглядит следующим образом:

void WriteIoCR(char cIndex, char cData)
{
//super IO of index port for Super I/O
//select super IO of index register for Super I/O
outportb(equIndexPort,cIndex);

//super IO of data for Super I/O
//write data to data register
outportb(equDataPort,cData);
}

Итак, cIndex должен быть 0x72, но как насчет cData? Я действительно не понимаю "|" вещь, поскольку я использовал это только для ИЛИ ("||") в условном выражении.

Ответы [ 5 ]

14 голосов
/ 23 мая 2011

Это побитовое or, в отличие от вашего обычного логического or. Это в основном устанавливает биты в целевой переменной, если был установлен соответствующий бит в любой из исходных переменных.

Например, выражение 43 | 17 может быть вычислено как:

43 = 0x2b = binary 0010 1011
17 = 0x11 = binary 0001 0001
                   ==== ====
        "or" them: 0011 1011 = 0x3b = 59

См. этот ответ для более тщательного изучения различных побитовых операторов.

Обычно используется, когда вы хотите манипулировать определенными битами в типе данных, например, управлять сторожевым таймером во встроенной системе (ваш конкретный случай использования).

Вы можете использовать or (|) для включения битов и and (&) для их отключения (с инверсией битовой маски, которая используется для их включения.

Итак, чтобы включить бит b3, используйте:

val = val | 0x08; // 0000 1000

Чтобы выключить его, используйте:

val = val & 0xf7; // 1111 0111

Чтобы определить, установлен ли b3, используйте:

if ((val & 0x08) != 0) {
    // it is set.
}

Обычно вы видите битовые маски, определенные как:

#define B0 0x01
#define B1 0x02
#define B2 0x04
#define B3 0x08
#define B4 0x10

или

enum BitMask {
    B0 = 0x01,
    B1 = 0x02,
    B2 = 0x04,
    B3 = 0x08,
    B4 = 0x10
};

Что это значит:

WriteIoCR (0x72, cSetWatchDogUnit|cSetTriggerSignal);

Скорее всего, 0x72 будет портом ввода-вывода какого-либо типа, к которому вы пишете, а cSetWatchDogUnit и cSetTriggerSignal будут битовыми масками, которые вы комбинируете для вывода команды (установите сигнал триггера и используйте значение единицы для сторожевого таймера). То, что эта команда означает на практике, можно сделать вывод, но вы безопаснее, обращаясь к документации для самой схемы сторожевого таймера.

И, если вы не знаете, что такое схема сторожевого таймера , для это простая схема, которая, если вы не пинаете ее достаточно часто (с другой *) 1047 *), она перезагрузит вашу систему, возможно, активировав контакт сброса на любом процессоре, который вы используете.

Это способ автоматически обнаруживать плохое поведение программного обеспечения и возвращать устройство в известное начальное состояние, соглашаясь с теорией, что лучше перезагрузить компьютер, чем продолжать плохо работать.

8 голосов
/ 23 мая 2011

Это поразрядно или .Используется здесь для объединения флагов.

1 голос
/ 23 мая 2011

| - это по битам или.Биты включаются (1 вместо 0), если включен один ИЛИ другой бит одного и того же целого в любом целом числе.

|| является логическим или.Он возвращает истину, если одно ИЛИ другое верно.

1 голос
/ 23 мая 2011

x | y обычно используется с Plain Old Datas в C / C ++.Это означает побитовое ИЛИ .

например,

char x = 0x1, y = 0x2;
x | y ==> 0x3

[Примечание: operator | может быть перегружено на class/struct в соответствии с вашими потребностями.]

0 голосов
/ 23 мая 2011

Хорошо, вот , почему вы используете побитовую или, или видите, что они используются, в такой ситуации.

Часто эти переменные являются флагами, которые используются для упаковки нескольких частей данных в один символ

Если cSetWatchDogUnit и cSetTriggerSignal

У

есть неперекрывающиеся биты (представьте cSetWatchDogUnit = 1 << 0 и cSetTriggerSignal = 1 << 1, вы можете проверить позже, чтобы увидеть, установлены ли они поразрядно, и, как в этом надуманном примере:

if cData & cSetWatchDogUnit
    do something
if cData & cSetTriggerSignal
    do something else

Все время оба эти флага могут быть упакованы и разосланы в одном символе. Таким образом, вы не заканчиваете передачей массива bools, вы можете добавить новые константы cSetSomeOtherDamnfoolThing = 1 << 2 и можете ссылаться на флаги как на переменные в вашем коде.

...