Диагностическое правило основано на руководстве MISRA (Motor Industry Software Reliability Association) по разработке программного обеспечения.
Правило актуально только для языка C.
Управляющее выражение конструкции _Generic (C11) не должно содержать каких-либо побочных эффектов, если выражение общего выбора не было получено через раскрытие макроса.
Такое ограничение обусловлено тем, что управляющее выражение никогда не вычисляется и, следовательно, любые побочные эффекты в нём не изменяют состояние программы.
К побочным эффектам относятся:
Рассмотрим пример:
#if SOME_CONDITION
#define DATA_TYPE int
#else
#define DATA_TYPE unsigned
#endif // SOME_CONDITION
typedef struct CustomType
{
DATA_TYPE data;
} *const CustomCPTR;
void InitializeData(const void *ptr)
{
CustomCPTR customData = (CustomCPTR)(ptr);
_Bool isOk = (_Generic(customData->data = 0
, unsigned int : 1
, default: 0));
if (!isOk) return;
// Do something
}
В коде приведена функция, которая должна каким-то образом инициализировать поле структуры. В начале делается проверка, что поле класса имеет подходящий тип. Вместе с этой проверкой выполняется инициализация поля data. Ожидалось, что при любом сценарии поле data будет инициализировано нулём. Однако инициализация не произойдёт, т.к. выражение customData->data = 0 находится в невычислимом контексте.
Исправить это можно так:
void InitializeData(const void *ptr) {
CustomCPTR customData = (CustomCPTR)(ptr);
customData->data = 0;
_Bool isOk = (_Generic(customData->data
, unsigned int : 1
, default: 0));
if (!isOk) return;
// Do something
}
Данная диагностика классифицируется как:
|