Расширение макроса в макросе - PullRequest
1 голос
/ 19 июня 2019

При тестировании программного обеспечения на Си я хотел бы использовать макросы для генерации вызовов функций. Использование компилятора codewarrior 5.2 (очень старого) - потому что у меня нет выбора, я не знаю, является ли это стандартным поведением.

в macros.h

#define RUNTEST(i)              \
  testcase_index = i;             \
  __PREFIX__##_testCase_##i()

в test_foo.c

#include "macros.h"
#define __PREFIX__ foo

RUNTEST(10);

По-видимому, __PREFIX__ не раскрывается, и препроцессор генерирует вызов на __PREFIX___testcase_10(), который, конечно, потерпит неудачу при связывании времени. Копирование всего в одном файле, кажется, ничего не меняет.

Есть ли простой выход?

Альтернативный

Я также попытался #define __PREFIX__() foo, чтобы вызвать расширение макроса. В этом случае он почти работает и теперь генерирует foo _testcase_10() (с пробелом), который, конечно, не будет компилироваться.

1 Ответ

0 голосов
/ 19 июня 2019

Я сделал упрощенную версию вашего вопроса здесь (без присвоения индекса тестового примера):

.h:

#define PASTER(x, y) x##_testCase_##y
#define EVAL(x, y) PASTER(x, y)
#define RUNTEST(i) EVAL(__PREFIX__, i)

.c

#define __PREFIX__ foo

// whatever

RUNTEST(1);

Объяснение:

Из стандарта C:

6.10.3.1 Подстановка аргумента

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

Так что теперь, когда у нас это есть, я пройдусь по расширению RUNTEST(1):

EVAL(__PREFIX__, i)
PASTER(foo, 1)
foo##_testCase_##1
foo_testCase_1
...