V2659. MISRA. Switch statements should be well-formed.
Диагностическое правило основано на руководстве MISRA (Motor Industry Software Reliability Association) по разработке программного обеспечения.
Правило актуально только для языка C.
В языке C конструкция switch обладает достаточно свободным синтаксисом. Отсутствие строгих правил может привести к написанию сложного неструктурированного кода. Для уменьшения вероятности допущения ошибки, а также для упрощения поддержки кода стандартом MISRA вводится понятие "well-formed" switch.
Чтобы пояснить, что такое "well-formed", введём ещё два определения:
1. case-group — последовательность из одного и более идущих подряд case label (которые могут включать default), например:
case 42:
//или
case 1: case 2: case 300:
//или
case 12:
default:
2. switch-clause — одно из следующего:
- statements*
break; - C90:
{declarations* statements*break; } - C99 and later:
{(declarations | statements)*break; }
Где * означает повторение 0 или более раз.
Например:
x = 5; y = 19; printf("%d", x); break;
//или
{ int x; int y; x = 5; y = x + 1; printf("%d", x); break; }
//или(кроме C90)
{ int x; x = 5; int y = x + 1; printf("%d", x); break; }
С учётом введённых определений "well-formed" switch можно представить в виде:
switch (expression)
{
case-group_1: switch-clause;
case-group_2: switch-clause;
....
case-group_n: switch-clause;
}
Также есть два дополнительных требования:
- метка
defaultобязана присутствовать и либо стоять в начале первойcase-group, либо в конце последней; - Количество
case-groupдолжно быть не меньше двух.
Примеры некорректных switch-statement:
switch (n)
{
case 1:
default: // <= (1)
case 2: n++; int x = 0; x++; break; // <= (2)
case 3: { n++; break; }
}
В данном примере присутствуют следующие нарушения:
- неправильно расположена метка
default: она должна быть либо первой в списке меток, либо последней; - некорректный
switch-clauseпослеcase 2: он содержит декларацию, которая не находится внутри блока.
switch (n)
{
case 10:
case 20: break;
}
В данном примере присутствуют следующие нарушения:
- отсутствует метка
default; - так как вторая метка
caseвходит в первую, то количествоcase-groupменьше двух. В таком случаеswitch-caseне имеет смысла.
switch (count % 4)
{
case 0: do { *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
} while (--n > 0);
}
В данном примере (знаменитый метод Даффа) присутствуют следующие нарушения:
- некорректный
switch-clause: отсутствуетbreak; - некорректный
case-group: меткиcase 3,case 2иcase 1находятся внутриswitch-clauseи образуют последовательностьcase-group, которая не находится непосредственно внутриswitch-case; - отсутствует метка
default.
Пример "well-formed" switch:
switch (n)
{
case 1: case 2: { n = 5; } break;
case 10:
case 20: break;
case 30: { int x; x = 4; printf("%d", x); break; }
default: if (n > 6) { n++; } break;
}
Данная диагностика классифицируется как:
|