V2669. MISRA. Tokens that look like a preprocessing directive should not occur within a macro argument.
Диагностическое правило основано на руководстве MISRA (Motor Industry Software Reliability Association) по разработке программного обеспечения.
Правило актуально только для С.
Токен, выглядящий как директива препроцессора, не должен использоваться как аргумент макроса. Использование директив препроцессора в качестве аргумента макроса ведёт к неопределённому поведению.
Рассмотрим пример:
#include <stdio.h
#define PRINT(arg) printf("%s", #arg)
int main(int argc, char *argv[])
{
PRINT(
#ifndef FLAG
My program prints: hello.
#else
My program prints: world.
#endif
);
}
Программист ожидает, что в зависимости от того, определён ли макрос FLAG, в stdout будет выведено или My program prints: hello, или My program prints: world. Поскольку поведение не определено, компилятор вправе сделать в этой ситуации всё, что хочет.
Если программа собрана с помощью GCC или Clang без макроопределения FLAG, то результат совпадёт с одним из вариантов, который ожидает программист:
My program prints: hello.
Однако программа, собранная MSVC, выведет неожиданный результат:
#ifndef FLAG My program prints: hello. #else My program prints: world. #endif
Исправленный код:
#include <stdio.h>
#define PRINT(arg) printf("%s", #arg)
int main(int argc, char *argv[])
{
#ifndef FLAG
PRINT(My program prints: hello.);
#else
PRINT(My program prints: world.);
#endif
}
Теперь все программы, собранные разными компиляторами, выводят текст одинаково в зависимости от макроопределения FLAG.
Данная диагностика классифицируется как:
|