Макросы препроцессора, которые работают с макросами? - PullRequest
0 голосов
/ 19 марта 2011

Вот пример моих макросов:

#define STR(val) #val
#define STRX(val) STR(val)
#define LINE_ STRX(__LINE__)
#define SRC_STR __FILE__":"LINE_
#define SRC_STRN SRC_STR"\n"

#define PRINT_IF(cond) ((cond)&&(printf("\""#cond"\" is true: "SRC_STRN)>=0))
#define PRINT_IFNOT(cond) ((!(cond))&&(printf("\""#cond"\" is false: "SRC_STRN)>=0))
#define PRINT_IFN PRINT_IFNOT
#define PRINT_IFEQ(a,b) PRINT_IF(a==b)

#define PRINT_FMT(val,fmt) printf(#val" = "#fmt": "SRC_STRN,val)
#define PRINT_INT(i) PRINT_FMT(i,%d)
#define PRINT_LONG(i) PRINT_FMT(i,%ld)
#define PRINT_UINT(i) PRINT_FMT(i,%u)
#define PRINT_ULONG(i) PRINT_FMT(i,%lu)
#define PRINT_HEX(i) PRINT_FMT(i,%x)
#define PRINT_FLT(flt) PRINT_FMT(flt,%g)
#define PRINT_PTR(ptr) PRINT_FMT(ptr,%p)
#define PRINT_STR(str) PRINT_FMT(str,%s)

Я хочу определить другой список макросов, связанных с этим, но я бы хотел избежать ввода всего. Я уже написал один пример:

#ifndef UNITTEST
#define PRINT_INT_U(x) ((void)sizeof(x))
#else
#define PRINT_INT_U(x) PRINT_INT(x)
#endif

Вы видите, что я хочу, чтобы мои PRINT_ ... _U функции ничего не оценивали, когда я не запускаю модульные тесты, чтобы я мог спамить их и не беспокоиться о том, что они всплывают повсюду во время отладка или производство.

Итак, мой вопрос: есть ли какой-нибудь сумасшедший метод, использующий препроцессор для генерации новых операторов #define? Я думаю, что нет ...

edit : Могу я хотя бы сделать что-то подобное? составить список:

INT
LONG
UINT
ULONG
HEX
FLT
PTR
STR

и затем вставьте их все в шаблон

#define PRINT_%LI%_U(x) PRINT_%LI%(x)

, где %LI% представляет элемент из списка.

Ответы [ 3 ]

1 голос
/ 19 марта 2011

Вам не нужно изменять определение всех макросов PRINT_TYPE: поскольку все они делегируются PRINT_FMT, вам просто нужно изменить определение этого макроса.

#ifndef UNITTEST
    #define PRINT_FMT(unused, unused) 0
#else
    #define PRINT_FMT(val,fmt) printf(#val" = "#fmt": "SRC_STRN,val)
#endif

(printf возвращает int, поэтому для согласованности имеет смысл иметь версию no-op типа int.)

0 голосов
/ 19 марта 2011

Как насчет этого:

#include <stdio.h>

#define FLAG

#ifdef FLAG
#define SW(x,...) x##_1(__VA_ARGS__)
#else
#define SW(x,...) x##_0(__VA_ARGS__)
#endif

#define TEST1(a) SW(TEST1,a)
#define TEST1_0(a) 10
#define TEST1_1(a) 11

#define TEST2(a,b) SW(TEST2,a,b)
#define TEST2_0(a,b) 20
#define TEST2_1(a,b) 21

#define TEST3() 32

int main( void ) {

  printf( "1. TEST1 = %i\n", TEST1(1) );
  printf( "2. TEST2 = %i\n", TEST2(1,2) );
  printf( "3. TEST3 = %i\n", TEST3() );

}

Возможно определить SW1, SW2 и т. Д. По количеству аргументов вместо вариационных макросов.

Надеюсь, достаточно ясно, что можно определить SW () для универсального отключения всех макросы, в зависимости от значения флага. Но макрос "определения" (через SW) и "реализации" по-прежнему нужны разные имена (нет «перегрузки макросов»), и его невозможно поставить #define в макрос.

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

0 голосов
/ 19 марта 2011

Хотя не совсем удовлетворительно, по крайней мере, следующий код повторно использует часть спецификатора формата.Я не уверен, что это действительно может вам помочь, но на всякий случай это может быть подсказка:

#define INT %d
#define LONG %ld
...and so forth...

#define PRINT(val,fmt) printf(#val" = "STRX(fmt)": "SRC_STRN,val)

#ifndef UNITTEST
#define PRINT_U(x,fmt) ((void)sizeof(x))
#else
#define PRINT_U(x,fmt) PRINT(x,fmt)
#endif

  int i;
  long l;
  PRINT( i, INT );
  PRINT( l, LONG );
  PRINT_U( i, INT );

Надеюсь, это поможет

...