2013-02-15 4 views
4

Я следующий цикл в C++, скомпилирован с г ++ 4.1.2:C++: Назначение результат побитового И к BOOL

while(1) { 
    int status = getStatus(); 
    bool firstOk = status & 0x1; 
    bool secondOk = status & 0x2; 
    if(firstOk != m_firstOk) { 
     logStatus(1, firstOk); 
     m_firstOk = firstOk; 
    } 
    if(secondOk != m_secondOk) { 
     logStatus(2, secondOk); 
     m_secondOk = secondOk; 
    } 

    sleep(1); 
} 

Примечание logStatus() получает свои параметры по значению, так что параметр не модифицировано. m_firstOk и m_secondOk - это, конечно, атрибуты bool member.

Это работало до сих пор. Я получил сообщение о том, что он не обнаружил, когда firstOk изменился. Я подключил к запущенному процессу с помощью gdb. Это было во время сна(), и я был поражен, когда увидел следующее:

(gdb) p m_firstOk 
$1 = true 
(gdb) p m_secondOk 
$2 = true 
(gdb) p firstOk 
$3 = 244 

WTF? Как firstOk может быть 244, когда он должен быть результатом побитового AND с 0x1? Я знаю, что логическое значение фактически хранится как целое число, но как его побитовое И игнорировать? Поскольку это 244, он оценивается как истинный, когда он должен быть ложным, что является причиной проблемы.

Не назначает результат побитового и логическому безопасному? Это ошибка gcc? Или я должен сделать что-то вроде следующего?

bool firstOk = (status & 0x1) ? true : false; 

Заранее спасибо.

+0

Звучит как неопределенное поведение. –

+0

Не должно ли 'status' быть без знака? – Pubby

+3

Вы уверены, что 'firstOk' существует во время вызова' sleep() '? Поскольку это простой bool и он больше не используется, он может быть повторно использован для чего-то другого. Что говорит 'logStatus()' say? – Csq

ответ

-1

Правильное назначение должно быть:

bool firstOk = (status & 0x1) == 0x01; 

Или вообще:

bool flag = (value & mask) == mask; 
+2

Ну, 1. это делает что-то другое (проверьте, присутствует ли вся маска против теста, если установлены некоторые биты маски) и 2. проблема, похоже, различна, а именно: '& 0x1' в коде OP кажется, оценивает что-то, имеющее больше бит. – leemes

+2

Я согласен с тем, что это превосходный способ работы с флагами, и что C++ не должен допускать неявные интегральные => 'bool' преобразования. Но это так, и код четко определен. –

0

Единственный способ, которым можно, если:

1) стек был перезаписан каким-то образом.

2) Значение временного значения не так важно, как только вы попадаете на линию сна, поэтому компилятор больше не отслеживает его, так что слот памяти может быть использован для чего-то еще!

Если он работает вначале, а затем позже начинает вести себя неправильно, то скорее всего это не ошибка компилятора для этого раздела кода.

+2

Нет, это неправильно. Интеграл преобразования => 'bool' четко определен, и соответствующие размеры типоразмеров не имеют значения. Не происходит усечения. И более того, то же самое верно в присваивании 'bool' и в' if', так что это вдвойне неправильно. –

+0

Я повторю это. – 2013-02-15 17:12:40

2

Локальные переменные firstOk и secondOk не «вживую», когда вы достигнете sleep() вызова, так что даже если они были были выделены слоты стека, это вполне возможно (и это вполне вероятно), что их значения не сохраняются где угодно больше.

Если вам нужно отладить любой из этих переменных, вам необходимо либо

  1. Заново объявить их как static, который выделит их постоянного хранения из стека
  2. Переместить декларацию firstOk и secondOk к внешнему охвату. (Примечание, этого может быть недостаточно, если вы не переместите их в область действия.)
  3. Скопируйте значения firstOk и secondOk в постоянные переменные или переменные, находящиеся во внешней области, и проверьте их.

В любом случае, после завершения процесса отладки я верну любую из вышеперечисленных мер отладки.:-)

Что касается вашего последнего вопроса, то заявление bool firstOk = status & 0x1 прекрасно, как и инструкция, которая следует за ним, установка secondOk. Присвоение intbool приводит к нулевому/ненулевому значениям false и true.

Что касается вашей реальной ошибки (как-то вы пропустили переход на firstOk), я не вижу, где вы могли бы потерять его в этом коде. Эта часть кода кажется прекрасной. Возможно ли, что ваша функция getStatus() должна вызываться чаще, чем раз в секунду? Может ли что-нибудь еще написать m_firstOk или m_secondOk? Их декларации не показаны, поэтому, по-видимому, они существуют во внешнем масштабе.

Смежные вопросы