exponenta event banner

Директива препроцессора в аргументе макроса

Директива препроцессора используется в аргументе к функциональному макросу

Описание

Этот дефект возникает при использовании директивы препроцессора в аргументе к функциональному макросу или функции, которая может быть реализована как функциональный макрос.

Например, #ifdef оператор встречается в аргументе для memcpy функция. memcpy функция может быть реализована как макрос.

memcpy(dest, src,
    #ifdef PLATFORM1
      12
    #else
      24
    #endif
  );
Средство проверки помечает подобное использование в printf и assert, которые также могут быть реализованы в виде макросов.

Риск

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

#define min(X, Y)  ((X) < (Y) ? (X) : (Y))
При звонке min(1,2), его заменяет кузов ((X) < (Y) ? (X) : (Y)). X и Y заменены на 1 и 2.

Согласно C11 Standard (Sec. 6.10.3), если список аргументов для самого функционально-подобного макроса имеет директивы предварительной обработки, подстановка аргументов во время предварительной обработки не определена.

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

Чтобы обеспечить однозначное замещение аргумента, используйте директивы препроцессора вне функционально-подобного макроса.

Например, для выполнения memcpy с различными аргументами, основанными на #ifdef директива, вызов memcpy несколько раз в пределах #ifdef ветки директивы.

#ifdef PLATFORM1
    memcpy(dest, src, 12);
#else
    memcpy(dest, src, 24);
#endif

Примеры

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

#include <stdio.h>

#define print(A) printf(#A)

void func(void) {
    print(
#ifdef SW
          "Message 1"
#else
          "Message 2"
#endif
         );
}

В этом примере директивы препроцессора #ifdef и #endif в аргументе к функциональному макросу print().

Исправление - использовать директивы вне макроса

Одной из возможных корректировок является многократное использование функционального макроса в ветвях #ifdef директива.

#include <stdio.h>

#define print(A) printf(#A)

void func(void) {
#ifdef SW
        print("Message 1");
#else  
        print("Message 2");
#endif 
}

Информация о результатах

Группа: Программирование
Язык: C | C++
По умолчанию: Вкл для рукописного кода, выкл для сгенерированного кода
Синтаксис командной строки: PRE_DIRECTIVE_MACRO_ARG
Воздействие: Низкий
Представлен в R2018a