﻿# V501\. Identical sub\-expressions to the left and to the right of 'foo' operator\.

Анализатор обнаружил фрагмент кода, который, скорее всего, содержит логическую ошибку\. В тексте программы имеется оператор \(<, \>, <\=, \>\=, \=\=, \!\=, &&, \|\|, \-, /\), слева и справа от которого расположены одинаковые подвыражения\. 

Рассмотрим пример: 

```cpp
if (a.x != 0 && a.x != 0)
```

В данном случае оператор '&&' окружен одинаковыми подвыражениями "a\.x \!\= 0", что позволяет обнаружить ошибку, допущенную по невнимательности\. Корректный код, который не вызовет подозрений у анализатора, будет выглядеть так:

```cpp
if (a.x != 0 && a.y != 0)
```

Рассмотрим другой пример ошибки, обнаруженный анализатором в коде реального приложения:

```cpp
class Foo {
  int iChilds[2];
  ...
  bool hasChilds() const { return(iChilds > 0 || iChilds > 0); }
  ...
}
```

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

```cpp
bool hasChilds() const { return(iChilds[0] > 0 || iChilds[1] > 0);}
```

Анализатор выдает предупреждение не во всех случаях, когда слева и справа от оператора находятся одинаковые подвыражения\.

Первое исключение относится к конструкциям, где используются оператор инкремента \+\+, декремента \-\-, а также \+\= и \-\=\. Пример взятый из реального приложения:

```cpp
do {
} while (*++scan == *++match && *++scan == *++match &&
         *++scan == *++match && *++scan == *++match &&
         *++scan == *++match && *++scan == *++match &&
         *++scan == *++match && *++scan == *++match &&
         scan < strend);
```

Данный код анализатор считает безопасным\.

Второе исключение относится к сравнению двух одинаковых чисел\. Этот прием часто используется программистами, чтобы выключить определенные ветки программы\. Пример:

```cpp
#if defined(_OPENMP)
#include <omp.h>
#else
#define omp_get_thread_num()   0
...
#endif
...
if (0 == omp_get_thread_num()) {
```

Последнее исключение относится к сравнению, где используются макросы:

```cpp
#define _WINVER_NT4_    0x0004
#define _WINVER_95_     0x0004
...
UINT    winver = g_App.m_pPrefs->GetWindowsVersion();
if(winver == _WINVER_95_ || winver == _WINVER_NT4_)
```

Следует понимать, что в ряде случаев анализатор может выдать предупреждение на корректную конструкцию\. Например, анализатор не учитывает побочные эффекты \(side effects\) при вызове функций:

```cpp
if (wr.takeChar() == '\0' && wr.takeChar() == '\0')
```

Другой пример ложного срабатывания анализатора был замечен на юнит\-тестах одного проекта, в той его части, где проверялось корректность работы перегруженного оператора '\=\=': 

```cpp
CHECK(VDStringA() == VDStringA(), true);
CHECK(VDStringA("abc") == VDStringA("abc"), true);
```

Диагностическое сообщение не выдается, если сравниваются два идентичных выражения типа float или double\. Такое сравнение позволяет определить, является ли значение NaN\. Пример кода, реализующего подобную проверку:

```cpp
bool isnan(double X) { return X != X; }
```