Макрос перегрузки типа

#c #macros #overloading #tostring #printf-debugging

#c #макросы #перегрузка #tostring #printf-отладка

Вопрос:

У меня есть куча вспомогательных макросов для отладки printf, и было бы довольно здорово не указывать тип, есть ли что-нибудь, что вы можете сделать, чтобы разрешить что-то вроде перегрузки макросов в c (может быть, специфичное для gcc, если оно доступно в gcc 4.3). Я подумал, может быть, typeof, но, видимо, это не работает.

пример макроса (у меня также есть некоторые цвета терминала ascii, которые я не могу вспомнить в верхней части моей головы)

 #ifdef _DEBUG
#define DPRINT_INT(x) printf("int %s is equal to %i at line %i",#x,x,__LINE__);
.
.
.
#else
#define DPRINT_INT(x)
.
.
.
#endif
  

Комментарии:

1. Можете ли вы привести пример ваших макросов?

Ответ №1:

Попробуйте это; он использует __встроенные методы gcc и автоматически определяет тип для вас, насколько это возможно, и создает простой отладочный макрос, где вам не нужно указывать тип. Конечно, вы можете сравнить typeof (x) с float и т.д. и т.п.

 #define DEBUG(x)                                                 
  ({                                                             
    if (__builtin_types_compatible_p (typeof (x), int))          
        fprintf(stderr,"%dn",x);                                
    else if (__builtin_types_compatible_p (typeof (x), char))    
        fprintf(stderr,"%cn",x);                                
    else if (__builtin_types_compatible_p (typeof (x), char[]))  
        fprintf(stderr,"%sn",x);                                
    else                                                         
        fprintf(stderr,"unknown typen");                        

  })
  

Комментарии:

1. Ура, это выглядит идеально. Спасибо, интересно, почему больше людей не используют это (накладные расходы во время выполнения)?

2. Потому что это ограничено GCC, и люди могут захотеть, чтобы код также компилировался с другими компиляторами.

3. Однако накладные расходы во время выполнения бесполезны — в любом случае, это для отладочной сборки, так что это будет #define’d во время обычной производственной сборки. Вероятно, он не широко используется, потому что он специфичен для gcc

4. Теперь, когда я вижу это, я начал представлять, как это можно было бы использовать для несколько безопасной перегрузки типов без длинных имен даже в обычном коде. Что касается специфики gcc, то в наши дни многие программы unix, вероятно, в какой-то степени специфичны для gcc (хотя это может измениться из-за llvm).

5. Некоторые, конечно, но не все , вот почему это не будет так широко использоваться.

Ответ №2:

Как насчет следующего макроса? Для этого по-прежнему требуется выбрать формат печати, но вам не придется переопределять все возможные варианты, и это также работает на MSVC:

 #define DPRINT(t,v) printf("The variable '%s' is equal to '%" ## #t ## "' on line %d.n",#v,v, __LINE__)
  

Чтобы использовать его:

 int var = 5;
const char *str = "test";
DPRINT(i,var);
DPRINT(s,str);
  

Комментарии:

1. Спасибо, но я пытался избежать такого рода вещей.

Ответ №3:

Я думаю, вы можете попробовать следующий код:

 #define DPRINT(fmt) do{ 
            my_printf fmt ; 
        } while(0)

my_printf( const char* szFormat, ... )
{
    char szDbgText[100];

    va_start(args, szFormat);
    vsnprintf(amp;szDbgText,99,szFormat,args);
    va_end(args);

    fprintf( stderr, "%s", szDbgText );
}
// usage
func( )
{
    int a = 5;
    char *ptr = "hello";

    DPRINT( ("a = %d, ptr = %sn", a, ptr) );
}
  

Примечание: При использовании DPRINT здесь используются двойные круглые скобки.

Комментарии:

1. Вы могли бы заставить свой макрос получить ... . Таким образом, вы могли бы избежать двойных круглых скобок.