exponenta event banner

CERT C: Rec. PRE11-C

Не завершайте определения макросов точкой с запятой

Описание

Определение правила

Не завершайте определения макросов точкой с запятой. [1 ]

Внедрение Polyspace

Эта проверка проверяет макрос, завершенный точкой с запятой.

Примеры

развернуть все

Проблема

Макрос, оканчивающийся точкой с запятой, возникает, когда макрос, вызываемый хотя бы один раз, имеет определение, оканчивающееся точкой с запятой.

Риск

Если определение макроса заканчивается точкой с запятой, расширение макроса может привести к непреднамеренной программной логике в определенных контекстах, например в выражении.

Например, рассмотрим макрос:

#define INC_BY_ONE(x) ++x;
Если используется в выражении:
res = INC_BY_ONE(x)%2;
выражение разрешается в:
res = ++x; %2;
Значение x+1 присвоен res, что, вероятно, непреднамеренно. Автономная инструкция leftover %2; является допустимым кодом C и может быть обнаружен только путем включения строгих предупреждений компилятора.

Зафиксировать

Не завершайте определения макросов точкой с запятой. При необходимости оставьте за пользователями макроса точку с запятой после макроса.

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

Пример - Ложная точка с запятой в определении макроса
#define WHILE_LOOP(n) while(n>0);

void performAction(int timeStep);

void main() {
    int loopIter = 100;
    WHILE_LOOP(loopIter) {
        performAction(loopIter);
        loopIter--;
    }
}

В этом примере дефект возникает из-за определения макроса WHILE_LOOP(n) заканчивается точкой с запятой. В результате использования точки с запятой while цикл имеет пустое тело, и следующие инструкции выполняются только один раз. Вероятно, предполагалось, что петля должна работать 100 раз.

Исправление - удаление точки с запятой из определения макроса

Удалите заключительную точку с запятой из определения макроса. При необходимости пользователи макроса могут добавить точку с запятой после макроса. В этом примере точка с запятой не требуется.

#define WHILE_LOOP(n) while(n>0)

void performAction(int timeStep);

void main() {
    int loopIter = 100;
    WHILE_LOOP(loopIter) {
        performAction(loopIter);
        loopIter--;
    }
}

Проверить информацию

Группа: Rec. 01. Препроцессор (PRE)
Представлен в R2020a

[1] Данное программное обеспечение было создано компанией MathWorks и включает в себя следующие компоненты: «Веб-сайт SEI CERT-C», © 2017 Университет Карнеги-Меллон, веб-сайт SEI CERT-C + + © 2017 Университет Карнеги-Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги-Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги-Меллон, со специальным разрешением от его Института программного обеспечения.

ЛЮБОЙ МАТЕРИАЛ УНИВЕРСИТЕТА КАРНЕГИ МЕЛЛОНА И/ИЛИ ЕГО ПРОГРАММНОГО ИНЖЕНЕРНОГО ИНСТИТУТА, СОДЕРЖАЩИЙСЯ В НАСТОЯЩЕМ ДОКУМЕНТЕ, ПОСТАВЛЯЕТСЯ КАК ЕСТЬ. УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ, ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, В ОТНОШЕНИИ ЛЮБЫХ ВОПРОСОВ, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ, ГАРАНТИИ ПРИГОДНОСТИ ДЛЯ ЦЕЛЕЙ ИЛИ ТОВАРНОЙ ПРИГОДНОСТИ, ИСКЛЮЧИТЕЛЬНОСТИ ИЛИ РЕЗУЛЬТАТОВ, ПОЛУЧЕННЫХ ОТ ИСПОЛЬЗОВАНИЯ УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ В ОТНОШЕНИИ СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКИХ ПРАВ.

Данное программное обеспечение и связанная с ним документация не были рассмотрены и не одобрены Университетом Карнеги-Меллона или его Институтом разработки программного обеспечения.