Мы используем куки, чтобы пользоваться сайтом было удобно.
Хорошо
to the top
close form

Заполните форму в два простых шага ниже:

Ваши контактные данные:

Шаг 1
Поздравляем! У вас есть промокод!

Тип желаемой лицензии:

Шаг 2
Team license
Enterprise license
** Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности
close form
Запросите информацию о ценах
Новая лицензия
Продление лицензии
--Выберите валюту--
USD
EUR
RUB
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Бесплатная лицензия PVS‑Studio для специалистов Microsoft MVP
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Для получения лицензии для вашего открытого
проекта заполните, пожалуйста, эту форму
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Мне интересно попробовать плагин на:
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
check circle
Ваше сообщение отправлено.

Мы ответим вам на


Если вы так и не получили ответ, пожалуйста, проверьте папку
Spam/Junk и нажмите на письме кнопку "Не спам".
Так Вы не пропустите ответы от нашей команды.

>
>
>
V2596. MISRA. The value of a composite …
menu mobile close menu
Проверка проектов
Сообщения PVS-Studio
Диагностики общего назначения (General Analysis, C++)
Диагностики общего назначения (General Analysis, C#)
Диагностики общего назначения (General Analysis, Java)
Микрооптимизации (C++)
Диагностика 64-битных ошибок (Viva64, C++)
Реализовано по запросам пользователей (C++)
Cтандарт MISRA
Стандарт AUTOSAR
Стандарт OWASP (C#)
Проблемы при работе анализатора кода
Дополнительная информация
toggle menu Оглавление

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

12 Июл 2021

Данное диагностическое правило основано на руководстве MISRA (Motor Industry Software Reliability Association) по разработке программного обеспечения.

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

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

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 определена модель сущностных типов (Essential type model). В этой модели переменная может иметь тип:

  • Boolean, если оперирует булевыми значениями true/false: '_Bool';
  • signed, если оперирует знаковыми целыми числами или является безымянным enum: 'signed char', 'signed short', 'signed int', 'signed long', 'signed long long', 'enum { .... };';
  • unsigned, если оперирует беззнаковыми целыми числами: 'unsigned char', 'unsigned short', 'unsigned int', 'unsigned long', 'unsigned long long';
  • floating, если оперирует числами с плавающей точкой: 'float', 'double', 'long double';
  • character, если оперирует только символами: 'char';
  • Именованный enum, если оперирует с именованным множеством определенных пользователем значений: 'enum name { .... };'.

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

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

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-битный размер.

Данная диагностика классифицируется как:

  • MISRA-C-10.6