Может ли этот оператор C / C ++ if () когда-либо иметь значение TRUE? - PullRequest
5 голосов
/ 11 ноября 2011

Согласно PC-lint , следующее утверждение никогда не будет TRUE:

if((variable & 0x02) == 1)

Я использую компилятор C для встроенных систем, который оценивает его как TRUEвсякий раз, когда установлен соответствующий бит в variable.Я предполагаю, что компилятор делает сравнение TRUE / FALSE обеих сторон == вместо сравнения полученных чисел.Другими словами, каждый раз, когда выражение (varable & 0x02) не равно нулю (то есть TRUE), оператор также будет TRUE, поскольку значение 1 is also TRUE (не ноль).

Я не знаюt знать, что стандарты C/C++ четко определяют, как должен вести себя компилятор в этом случае.Существуют ли C/C++ эксперты, которые могут ответить на этот вопрос, основываясь на том, что говорят стандарты (например, C90, C99, и т. Д.)?

PS: В приведенном выше утверждении «переменная» - это знак без знака.

Ответы [ 6 ]

11 голосов
/ 11 ноября 2011

ПК-линт прав. Предполагая, что var является целочисленной переменной, выражение var & 0x02 может принимать два значения: 0 и 2. Оно никогда не будет равно 1, что и проверяется оператором if.

Чтобы расширить это, оператор равенства применяется к двум целочисленным значениям. Важно то, оценивают ли оба операнда одно и то же число, а не то, являются ли они одновременно «истинными» или «ложными».

Чтобы проверить, установлен ли бит 1, можно использовать:

if (variable & 0x02) {
  ...
}

Учитывая, что ваш компилятор ведет себя так, как вы говорите, он явно несовместим. Тем не менее, он почти наверняка будет правильно обрабатывать if (variable & 0x02). Я бы порекомендовал исправить код, чтобы он не сломался, если бы вы когда-нибудь меняли компиляторы.

Наконец, ситуация отличается, если: (1) код - C ++, а не C; и (2) variable является экземпляром класса; и (3) класс перегружает рассматриваемые операторы. В этом случае поведение сводится к тому, что фактически делают перегруженные операторы.

6 голосов
/ 11 ноября 2011

В C ++ это может привести к истинному значению, если (и только если) variable является экземпляром класса с перегруженной operator&, которая не соответствует нормальной побитовой И семантике.

В C это условие всегда будет ложным. §6.5.10 определяет семантику побитового оператора AND, и это довольно просто и точно:

4. Результатом двоичного оператора & является побитовое И операндов (то есть каждый бит в результат устанавливается тогда и только тогда, когда каждый из соответствующих битов в преобразованных операндах равен набор).

Понятно, что результатом не может быть 1, поскольку бит 1 не установлен в преобразованном значении правого операнда (а именно, 0x02).

Естественно, если неопределенное поведение было вызвано в какой-то момент в прошлом программы (или во время компиляции!), Тогда может произойти все что угодно. Однако, за исключением этой возможности, ваш компилятор несовместим. То есть сломан. К сожалению, это чрезвычайно часто встречается на нечетных встроенных компиляторах. Если вам повезет, вы даже сможете сообщить об ошибке и исправить ее.

4 голосов
/ 11 ноября 2011

Я не думаю, что стандарт определяет что-либо об этой очень специфической и необычной проблеме.Как говорит aix, это утверждение никогда не может быть истинным, потому что (в двоичном виде):

XXXX XXXX -> variable
0000 0010 -> 0x02
--------- AND
0000 00X0 -> result

(упрощение до 8-битных типов)

Таким образом, ваши единственные результаты могут быть 0000 0010 (чторавно 2) или 0000 0000 (что равно 0).

1 голос
/ 11 ноября 2011

Для C ответ - нет.

Стандарт C говорит о & (6.5.10):

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

Поскольку в 2 установлен только бит 1, значение выражения может иметь только бит 1. Он не может принимать никаких других значений, кроме 2 и 0. Ни 2, ни 0 не могут сравниваться равными 1.

Битовые представления целых чисел определены в 6.2.6.2 (для неотрицательных значений обычным способом).

0 голосов
/ 11 ноября 2011

Рассмотрим двоичное значение 2

  02 = 0010 (say a 4 bit number)

, а двоичное значение 1 равно

  01 = 0001 

Младший двоичный бит 2 всегда равен нулю, то есть самый левыйбит равен 0. SO
Операция & (and) с 0 никогда не дает 1, поэтому мы можем сказать, что она никогда не может быть равна 1

      0 0 =>    0
      0 1 =>    0
      1 1 =>    1 

Примечание: & указывает на бит и операцию

   2 - 0010
   3 - 0011
       0010

Таким образом, результат с xx & 2 будет 0 или 2.

0 голосов
/ 11 ноября 2011

По существу, пух здесь.По крайней мере, на любой платформе, о которой я знаю, условие будет ложным.Посмотрите на битовое представление чисел: x & 2 (0010) всегда будет либо нулем, либо 2 (0010) и, таким образом, будет отличаться от 1 (0001) для любого целого числа x.

...