Создание имен функций со строками с помощью макросов в C

у меня две функции:

void foo0(int bar);
void foo1(int bar);

Я не хочу иметь возможность создать макрос QUX это расширится до этих имен функций на основе другого макроса BAZ. Я попробовал следующее:

#define BAZ 0
#define QUX(x) foo##BAZ(x)

но это не сработало, так как сгенерированные функции fooBAZ(). Как я могу заставить его генерировать foo0()?

5 ответов


#define CAT_I(a,b) a##b
#define CAT(a,b) CAT_I(a, b)
#define QUX(x) CAT(foo, BAZ) ## (x)

#include <stdio.h>

#define ONE 1
#define ZERO 0

#define GLUE_HELPER(x, y) x##y
#define GLUE(x, y) GLUE_HELPER(x, y)

int foo0(int x)
{
    printf("\n foo0...%d\n", x);
}

int foo1(int x)
{
    printf("\n foo1...%d\n",x);
}

int main()
{
   //Calling Function
   GLUE(foo,ZERO)(5);    
   GLUE(foo,ONE)(10);    
   return 0;
}

будет работать, как ожидалось. Вы должны сделать string concate в расширении макроса второго уровня.


либо имеют промежуточный макрос, который оценивает еще раз

#define QUX_0(A) foo ## A
#define QUX_1(A) QUX_0(A)
#define QUX(x) QUX_1(BAZ)(x)

или, может быть, еще проще с

#define fooBAZ foo0

Кстати: Ваш второй ## должна произойти ошибка на соответствующем компиляторе. Также не ставьте ; В конце определения макроса он укусит вас.


Если есть только две возможности:

#if BAZ == 0
#define QUX(X) foo0(x)
#else
#define QUX(X) foo1(x)
#endif

вот решение, которое я придумал после прочтения немного онлайн. В принципе, чтобы получить номер, который должен отображаться в подписи, вам нужно stringify аргумент. Если вы строите аргумент, прескан не завершается, что приводит к определению функции fooBAZ (он не полностью развернут)

Если вы используете другого посредника макроса, он завершит расширение.

здесь ссылке это объясняет далее о prescan и раз это не завершено.

// Testing.cpp : Defines the entry point for the console application.
//
#include <stdio.h>

#define BAZ 0

#define QUXdef(x) QUX(x)
#define QUX(x) foo##x()

#define QUXimp(x) DEF(x)
#define DEF(x) foo##x()


//Function Def
void QUXdef(BAZ);

int main(int argc, char* argv[])
{
    foo0();
}

void QUXimp(BAZ)
{
    printf("Hello world\n");
}

примечание: Я включил другой набор макросов для реализации функции. Вы не просили об этом, но я подумал, что это было бы более "полным", если бы определение и реализация функций были вашей целью. QUXdef и QUX выполняют ваши конкретные потребности.

Edit 1:

  • я удалил код в стиле C++из решения. Это было доведено до моего сведения Йенс Gustedt и является допустимой критики рассматривают этот был помечен как C(моя вина не читаю полностью).
  • я также удалил; сформировать сам макрос. Теперь он поставляется пользователем вместо этого, который является гораздо более читаемым. Это был действительный критика от Йенс Gustedt
  • я взял void из расширения макросов. Вместо этого я позволил пользователю определить тип возврата. Мне кажется, что это также обеспечивает большую читаемость.
  • я удалил оператор stdafx, учитывая, что это для кода C, и visual studio с меньшей вероятностью будет использоваться чистым C программисты. Когда он сидит, это должно быть скопировано и вставлено в файл, а затем скомпилировано GCC или другим более популярным компилятором C.

в противном случае этот ответ является твердым, и если вы посмотрите на ссылку, которую я предоставил, это объясняет необходимость промежуточного макроса для получения надлежащего расширения, которое ищет Asker.