V1119. Preprocessing directive is present within a macro argument. This leads to undefined behavior.
Токен, выглядящий как директива препроцессора, не должен использоваться как аргумент макроса. Использование директив препроцессора в качестве аргумента макроса ведёт к неопределённому поведению.
Рассмотрим пример:
#include <stdio.h
#define PRINT(arg) printf("%s", #arg)
int main(int argc, char *argv[])
{
PRINT(My program prints:
#ifndef FLAG
hello.
#else
world.
#endif
);
}
Программист ожидает, что в зависимости от того, определён ли макрос FLAG, в stdout будет выведено или My program prints: hello, или My program prints: world. Поскольку поведение не определено, компилятор вправе сделать в этой ситуации всё, что хочет.
Если программа собрана с помощью GCC или Clang без макроопределения FLAG, то результат совпадёт с одним из вариантов, который ожидает программист:
My program prints: hello.
Однако программа, собранная MSVC, выведет неожиданный результат:
My program prints: #ifndef FLAG hello. #else 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.