V2572. MISRA. Value of the expression should not be converted to the different essential type or the narrower essential type.
Данное диагностическое правило основано на руководстве MISRA (Motor Industry Software Reliability Association) по разработке программного обеспечения.
Данное диагностическое правило актуально только для C. Язык C предоставляет свободу при проведении присваиваний между объектами различных арифметических типов. Однако подобные неявные преобразования могут приводить к неочевидным проблемам, таким как потеря знака, точности или значимости.
Стандарт 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 { .... };'.
Указатели в этой модели отсутствуют.
Используя модель сущностных типов, можно уменьшить количество подобных неочевидных проблем путем присваивания переменным значений одного и того же сущностного типа. При этом разрешается присваивать в переменную более широкого сущностного типа значения более узкого. Запрещается производить неявные преобразования значений из одного сущностного типа в другой.
Исключения:
- Неотрицательное константное выражение сущностного знакового типа может быть присвоено объекту сущностного беззнакового типа, если значение может быть представлено в этом типе.
- Инициализатор '{ 0 }' может использоваться для инициализации агрегатного типа или объединения.
Пример кода, на который анализатор выдаст предупреждения:
typedef enum ENUM {ONE} ENUM;
void Positive(signed char x)
{
unsigned char uchr = x; // <=
unsigned short usht = x; // <=
unsigned int uit = x; // <=
unsigned long ulg = x; // <=
unsigned long long ullg = x; // <=
long double ld = 0.0;
double d = ld; // <=
float f = d; // <=
ENUM e = x; // <=
}
Пример правильного с точки зрения этой диагностики кода:
enum {ONE = 1, TWO, THREE, FOUR, FIVE, SIX,
MUCH = 123123, MORE = 0x7FFFFFFF-1};
void Negative()
{
signed char c = ONE; // ok
signed short h = TWO; // ok
signed int i = THREE; // ok
signed long long ll = FOUR; // ok
unsigned char uc = FIVE; // ok
unsigned short uh = SIX; // ok
unsigned int ui = MUCH; // ok
unsigned long long ull = MORE; // ok
float f = 0.0f; // ok
double d = f; // ok
long double ld = d; // ok
ENUM e = c; // ok
}
Данная диагностика классифицируется как:
|