Предотвращение неправильного использования логических операторов вместо побитовых операторов - PullRequest
2 голосов
/ 11 июня 2009

В C ++ можно использовать логический оператор, для которого был задан двухсторонний оператор:

int unmasked = getUnmasked(); //some wide value
int masked = unmasked & 0xFF; // izolate lowest 8 bits

второе утверждение может быть легко опечатано:

int masked = unmasked && 0xFF; //&& used instead of &

Это приведет к некорректному поведению - masked теперь будет 0 или 1, когда предполагается, что оно от 0 до 255. И C ++ никогда не будет жаловаться.

Можно ли спроектировать код таким образом, чтобы такие ошибки обнаруживались на уровне компилятора?

Ответы [ 4 ]

4 голосов
/ 11 июня 2009

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

Так что вместо:

int masked = unmasked & 0xFF; // izolate lowest 8 bits

Вы пишете:

int masked = GetLowestByte(unmasked);

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

Только в одном месте (реализация GetLowestByte и его сестер) у вас будут реальные побитовые операции. Затем вы можете прочитать эти строки два или три раза, чтобы увидеть, если вы это испортили. Более того, вы можете выполнить модульное тестирование этой части.

3 голосов
/ 11 июня 2009

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

Я думаю, что единственный способ убедиться в этом - определить стандарты кодирования, чтобы сделать различие между двумя операторами более очевидным - что-то вроде:

template<typename T>
T BitwiseAnd( T value, T mask ) { return value & mask; }

и запретить побитовые операторы & и |

3 голосов
/ 11 июня 2009

Это немного Капитан Очевидность , но вы, конечно, можете применить инкапсуляцию и просто спрятать битовую маску внутри класса. Затем вы можете использовать перегрузку оператора, чтобы убедиться, что логическое значение operator&&() соответствует вашему усмотрению.

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

2 голосов
/ 11 июня 2009

Оба оператора представляют допустимые операции над целыми числами, поэтому я не вижу способа обнаружить проблему. Как компилятор должен знать, какую операцию вы действительно хотите?

...