﻿# V2596\. MISRA\. The value of a composite expression should not be assigned to an object with wider essential type\.

Диагностическое правило основано на руководстве [MISRA](https://www.misra.org.uk/) \(Motor Industry Software Reliability Association\) по разработке программного обеспечения\.

Диагностическое правило актуально только для C\.

Язык C предоставляет свободу при проведении присваиваний между объектами различных арифметических типов\. Однако неявные преобразования при подобных присваиваниях могут приводить к неочевидным проблемам, таким как потеря знака, точности или значимости\.

Рассмотрим следующий фрагмент кода:

```cpp
void foo()
{
  ....
  uint16_t var_a = 30000;
  uint16_t var_b = 40000;
  uint32_t var_sum;
  var_sum = var_a + var_b;  /* var_sum = 70000 or 4464? */
  ....
}
```

При вычислении значения, которое будет присвоено переменной `var_sum`, происходит неявное преобразование из типа `uint16_t` к `int`\. Как следствие, результат присваивания зависит от размера типа `int`:

* если `int` имеет 32\-битный размер, то вычисления будут выполнены по модулю `2^32`, и в переменную `var_sum` будет записано ожидаемое значение `70000`;
* если `int` имеет 16\-битный размер, то вычисления будут выполнены по модулю `2^16`, и в переменную `var_sum` будет записано значение `70000 % 65536 == 4464`\.

Стандарт MISRA C определяет собственную модель типов — [Essential type model](https://pvs-studio.ru/ru/blog/terms/7007/)\.

Используя модель сущностных типов, можно уменьшить количество подобных неочевидных проблем\. Для этого следует избегать присвоения составных выражений, имеющих меньший сущностный тип, в переменные и аргументы функций, имеющие более широкий сущностный тип\.

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

```cpp
void foo()
{
  ....
  uint16_t var_a = 30 000;
  uint16_t var_b = 40 000;
  uint32_t var_sum;
  var_sum = (uint32_t)var_a + var_b;  /* var_sum = 70 000 */
  ....
};
```

Теперь вычисления происходят по модулю `2^32` независимо от того, какой размер имеет `int`, и ошибка не возникает, даже если `int` имеет 16\-битный размер\.