﻿# V2669\. MISRA\. Tokens that look like a preprocessing directive should not occur within a macro argument\.

Диагностическое правило основано на руководстве [MISRA](https://misra.org.uk/) \(Motor Industry Software Reliability Association\) по разработке программного обеспечения\.

Правило актуально только для С\.

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

Рассмотрим пример:

```cpp
#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](https://godbolt.org/z/PT4nh645b) или [Clang](https://godbolt.org/z/c6zPoaovK) без макроопределения `FLAG`, то результат совпадёт с одним из вариантов, который ожидает программист:

```cpp
My program prints: hello.
```

Однако программа, собранная [MSVC](https://godbolt.org/z/8x3K9fq81), выведет неожиданный результат:

```cpp
#ifndef FLAG My program prints: hello. #else My program prints: world. #endif
```

Исправленный код:

```cpp
#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 
}
```

Теперь все программы, собранные разными компиляторами, [выводят текст одинаково](https://godbolt.org/z/4KEcr4xvd) в зависимости от макроопределения `FLAG`\.