﻿# V674\. Expression contains a suspicious mix of integer and real types\.

Анализатор обнаружил потенциальную ошибку в выражении, где совместно используются целочисленные и real\-типы данных\. Под real\-типами понимаются такие типы, как float/double/long double\.

Рассмотрим для начала самый простой случай\. Литерал, имеющий тип 'double' неявно приводится к целочисленному типу\. Это может указывать на наличии программной ошибки\.

```cpp
int a = 1.1;
```

Этот код не имеет практического смысла\. Скорее всего, переменная должна была быть инициализирована другим значением\.

Показанный выше пример надуманный и не интересен\. Давайте посмотрим, как проявляет себя эта ошибка на практике\.

Пример 1\.

```cpp
int16u object_layer_width;
int16u object_layer_height;
if (object_layer_width == 0 ||
    object_layer_height == 0 ||
    object_layer_width/object_layer_height < 0.1 ||
    object_layer_width/object_layer_height > 10)
```

Здесь целочисленное значение сравнивается с константой '0\.1'\. Это очень подозрительно\. Предположим, что переменные имеют следующие значения:

* object\_layer\_width \= 20;
* object\_layer\_height \= 100;

Программист ожидает, что при делении этих чисел результат будет равен '0\.2'\. Это подходящее значение, так оно попадает в диапазон \[0\.1\.\.10\]\.

На самом деле, результат деления будет равен 0\. Деление осуществляется над целочисленными типами данных\. Потом, при сравнении с '0\.1' произойдет расширение до типа 'double', но будет уже поздно\. Чтобы исправить код необходимо заранее использовать явное приведение типов:

```cpp
if (object_layer_width == 0 ||
    object_layer_height == 0 ||
    (double)object_layer_width/object_layer_height < 0.1 ||
    (double)object_layer_width/object_layer_height > 10.0)
```



Второй пример\.

```cpp
// be_aas_reach.c
ladderface1vertical =
  abs( DotProduct( plane1->normal, up ) ) < 0.1;
```

Аргумент функции abs\(\) имеет тип 'double'\. На первый взгляд, код кажется абсолютно правильным и хочется заявить "анализатор здесь сглупил"\.

Но давайте разберёмся более детально\. Давайте посмотрим, как объявлена функция abs\(\) в заголовочных файлах\.

```cpp
int __cdecl abs( int _X);
#ifdef __cplusplus
extern "C++" {
  inline long __CRTDECL abs(__in long _X) { .... }
  inline double __CRTDECL abs(__in double _X) { .... }
  inline float __CRTDECL abs(__in float _X) { .... }
}
#endif
```

Да, в Си\+\+ функции abs\(\) перегружены для различных типов\. Однако, мы имеем дело с кодом на языке Си \(файл be\_aas\_reach\.c\)\.

Это значит, что выражение типа 'float' будет неявно преобразовано к типу 'int'\. И результат работы функции abs\(\) тоже будет иметь тип 'int'\. Значение типа 'int' нет смысла сравнивать с '0\.1'\. Об этом и предупреждает анализатор\.

В программах на языке Си для правильного вычисления модуля потребуется другая стандартная функция:

```cpp
double  __cdecl fabs(__in double _X);
```

Исправленный код:

```cpp
ladderface1vertical =
  fabs( DotProduct( plane1->normal, up ) ) < 0.1;
```